 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Jamie Burns Guest
|
Posted: Tue Jan 27, 2004 8:50 pm Post subject: typeid() faster than dynamic_cast<> |
|
|
Hello,
I just did a simple benchmark:
for (xx=0;xx<100000;xx++) {
rDerived* derived = dynamic_cast
if (derived) derived->setValue(message.data.messageSetInt.value);
}
against:
for (xx=0;xx<100000;xx++) {
if (typeid(object) == typeid(rDerived*)) ((rDerived*)
object)->setValue(message.data.messageSetInt.value);
}
And the latter case blew the former out of the water. Using typeid() with a
C style cast was 94 times faster than using dynamic_cast<>.
So is it really better to use typeid() and a C style cast rather than the
(apparantly) slower dynamic_cast<>?
Jamie Burns.
|
|
| Back to top |
|
 |
Alf P. Steinbach Guest
|
Posted: Tue Jan 27, 2004 9:01 pm Post subject: Re: typeid() faster than dynamic_cast<> |
|
|
On Tue, 27 Jan 2004 20:50:02 -0000, "Jamie Burns" <sephana (AT) email (DOT) com> wrote:
| Quote: | I just did a simple benchmark:
for (xx=0;xx<100000;xx++) {
rDerived* derived = dynamic_cast
if (derived) derived->setValue(message.data.messageSetInt.value);
}
against:
for (xx=0;xx<100000;xx++) {
if (typeid(object) == typeid(rDerived*)) ((rDerived*)
object)->setValue(message.data.messageSetInt.value);
}
And the latter case blew the former out of the water. Using typeid() with a
C style cast was 94 times faster than using dynamic_cast<>.
|
In general this is a quality-of-implementation issue. A factor of 94
for this code seems excessive. To say the least.
| Quote: | So is it really better to use typeid() and a C style cast rather than the
(apparantly) slower dynamic_cast<>?
|
Assuming you meant to write 'static_cast', not 'C style cast', which you
should never use:
It depends. With dynamic_cast you allow a wider range of actual types for
'object' than you do with typeid. With typeid you tell the compiler that
you're only interested in one particular type, and so it can be faster,
as well as more specifically expressing the intent of the code.
Btw., why not use '++xx', and why not declare 'xx' in the loop?
|
|
| Back to top |
|
 |
lilburne Guest
|
Posted: Tue Jan 27, 2004 9:05 pm Post subject: Re: typeid() faster than dynamic_cast<> |
|
|
Jamie Burns wrote:
| Quote: |
And the latter case blew the former out of the water. Using typeid() with a
C style cast was 94 times faster than using dynamic_cast<>.
So is it really better to use typeid() and a C style cast rather than the
(apparantly) slower dynamic_cast<>?
|
What if rDerived is actually sDerived, which version is
correct then?
|
|
| Back to top |
|
 |
Pete Becker Guest
|
Posted: Tue Jan 27, 2004 10:12 pm Post subject: Re: typeid() faster than dynamic_cast<> |
|
|
Jamie Burns wrote:
| Quote: |
So is it really better to use typeid() and a C style cast rather than the
(apparantly) slower dynamic_cast<>?
|
They do different things. When you compare typeids you're only making
one comparison. When you use dynamic_cast you're walking the inheritance
hierarchy looking for a type match. Of course, the benefit of the latter
is that it actually gets the right answer if you change your inheritance
hierarchy in various ways.
Using typeid is only "better" if you don't care how robust the code is
and you've determined that the type comparison is a bottleneck in your
application.
--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
|
|
| Back to top |
|
 |
Jonathan Turkanis Guest
|
Posted: Tue Jan 27, 2004 10:44 pm Post subject: Re: typeid() faster than dynamic_cast<> |
|
|
"Jamie Burns" <sephana (AT) email (DOT) com> wrote
| Quote: | Hello,
I just did a simple benchmark:
for (xx=0;xx<100000;xx++) {
rDerived* derived = dynamic_cast
if (derived) derived->setValue(message.data.messageSetInt.value);
}
against:
for (xx=0;xx<100000;xx++) {
if (typeid(object) == typeid(rDerived*)) ((rDerived*)
object)->setValue(message.data.messageSetInt.value);
}
|
I think you might be making a simple mistake. A pointer is not a
polymorphic type, so typeid(T*) returns a type_info object
representing the static pointer type T*. An expression of the form
typeid(rDerived*) returns a type_info object represent the type
rDerived*. Likewise, if 'object' is decalred:
Base* object;
then typeid(object) should return a type_info object representing the
type Base*.
The condition in the second loop can be evaluated partly at compile
time, since the static types are known. If 'object' is decalred as
above, the condition will never hold, and the function calls will be
skipped. Have you verified that the function setValue is actually
being called?
Jonathan
|
|
| Back to top |
|
 |
David White Guest
|
Posted: Tue Jan 27, 2004 11:08 pm Post subject: Re: typeid() faster than dynamic_cast<> |
|
|
"Jamie Burns" <sephana (AT) email (DOT) com> wrote
| Quote: | Hello,
I just did a simple benchmark:
for (xx=0;xx<100000;xx++) {
rDerived* derived = dynamic_cast
if (derived) derived->setValue(message.data.messageSetInt.value);
}
against:
for (xx=0;xx<100000;xx++) {
if (typeid(object) == typeid(rDerived*)) ((rDerived*)
object)->setValue(message.data.messageSetInt.value);
}
And the latter case blew the former out of the water. Using typeid() with
a
C style cast was 94 times faster than using dynamic_cast<>.
|
In a similar benchmark using VC++ 7.0 optimized for speed, I found the
dynamic_cast version to take between 3 and 4 times as long as the typeid
version. This is not surprising considering what they each do, but a factor
of 94 is a surprise.
| Quote: | So is it really better to use typeid() and a C style cast rather than the
(apparantly) slower dynamic_cast<>?
|
No. They do different things. They are interchangeable only if there are no
classes derived from rDerived, or you want to ignore them (unlikely, since a
class derived from rDerived IS-A rDerived). Even if there are no classes
derived from rDerived now, there might be later, and you wouldn't want your
code to break. Unless you really need to squeeze every drop of speed out of
the machine, using typeid for this purpose is a bad move.
DW
|
|
| Back to top |
|
 |
Andrey Tarasevich Guest
|
Posted: Wed Jan 28, 2004 12:42 am Post subject: Re: typeid() faster than dynamic_cast<> |
|
|
Jonathan Turkanis wrote:
| Quote: | ...
I just did a simple benchmark:
for (xx=0;xx<100000;xx++) {
rDerived* derived = dynamic_cast
if (derived) derived->setValue(message.data.messageSetInt.value);
}
against:
for (xx=0;xx<100000;xx++) {
if (typeid(object) == typeid(rDerived*)) ((rDerived*)
object)->setValue(message.data.messageSetInt.value);
}
I think you might be making a simple mistake. A pointer is not a
polymorphic type, so typeid(T*) returns a type_info object
representing the static pointer type T*. An expression of the form
typeid(rDerived*) returns a type_info object represent the type
rDerived*. Likewise, if 'object' is decalred:
Base* object;
then typeid(object) should return a type_info object representing the
type Base*.
...
|
Nice catch. It appears that no one else noticed this. The second test
('typeid') does not do what OP intended it to do. The 'if' statement in
the second loop should look as follows
...
if (typeid(*object) == typeid(rDerived))
...
--
Best regards,
Andrey Tarasevich
|
|
| Back to top |
|
 |
Pete Becker Guest
|
Posted: Wed Jan 28, 2004 12:59 am Post subject: Re: typeid() faster than dynamic_cast<> |
|
|
Andrey Tarasevich wrote:
| Quote: |
Jonathan Turkanis wrote:
...
I just did a simple benchmark:
for (xx=0;xx<100000;xx++) {
rDerived* derived = dynamic_cast
if (derived) derived->setValue(message.data.messageSetInt.value);
}
against:
for (xx=0;xx<100000;xx++) {
if (typeid(object) == typeid(rDerived*)) ((rDerived*)
object)->setValue(message.data.messageSetInt.value);
}
I think you might be making a simple mistake. A pointer is not a
polymorphic type, so typeid(T*) returns a type_info object
representing the static pointer type T*. An expression of the form
typeid(rDerived*) returns a type_info object represent the type
rDerived*. Likewise, if 'object' is decalred:
Base* object;
then typeid(object) should return a type_info object representing the
type Base*.
...
Nice catch. It appears that no one else noticed this. The second test
('typeid') does not do what OP intended it to do. The 'if' statement in
the second loop should look as follows
...
if (typeid(*object) == typeid(rDerived))
...
|
Of course, given the number of typos in the "code", it's not really
possible to tell whether that's what he did.
--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
|
|
| Back to top |
|
 |
Hendrik Belitz Guest
|
Posted: Wed Jan 28, 2004 8:14 am Post subject: Re: typeid() faster than dynamic_cast<> |
|
|
Jamie Burns wrote:
| Quote: | So is it really better to use typeid() and a C style cast rather than the
(apparantly) slower dynamic_cast<>?
|
The best way is not to use that stuff at all. Ask yourself if your software
design is really good. Most of the time using the RTTI functionality is
only a hint to a bad program design. AFAIK there is only one useful
application of RTTI, and that's emulating weak typing in C++.
--
To get my real email adress, remove the two onkas
--
Dipl.-Inform. Hendrik Belitz
Central Institute of Electronics
Research Center Juelich
|
|
| Back to top |
|
 |
lilburne Guest
|
Posted: Wed Jan 28, 2004 9:24 am Post subject: Re: typeid() faster than dynamic_cast<> |
|
|
Hendrik Belitz wrote:
| Quote: | Jamie Burns wrote:
So is it really better to use typeid() and a C style cast rather than the
(apparantly) slower dynamic_cast<>?
The best way is not to use that stuff at all. Ask yourself if your software
design is really good. Most of the time using the RTTI functionality is
only a hint to a bad program design. AFAIK there is only one useful
application of RTTI, and that's emulating weak typing in C++.
|
Not quite! Lets say I have a class Curve and derived classes
representing line, circular arc, bezier, nurb, composites. And given two
Curves I want to find the points where they intersect. Now I can write
a general method for this, but if I know (RTTI) that the both entities
are lines, or both are arcs, then I can provide a more efficent solution
for these special cases.
|
|
| Back to top |
|
 |
Klaus Nowikow Guest
|
Posted: Wed Jan 28, 2004 9:52 am Post subject: Re: typeid() faster than dynamic_cast<> |
|
|
Hendrik Belitz wrote:
| Quote: | Jamie Burns wrote:
So is it really better to use typeid() and a C style cast rather than the
(apparantly) slower dynamic_cast<>?
The best way is not to use that stuff at all. Ask yourself if your software
design is really good. Most of the time using the RTTI functionality is
only a hint to a bad program design. AFAIK there is only one useful
application of RTTI, and that's emulating weak typing in C++.
|
Well, I don't think dynamic_cast<>ing from one abstract base class
to another abstract base class (interface) is the bad thing.
It's the _downcast_ that shows poor class design.
--
Klaus
|
|
| Back to top |
|
 |
Nick Hounsome Guest
|
Posted: Thu Jan 29, 2004 8:54 pm Post subject: Re: typeid() faster than dynamic_cast<> |
|
|
"lilburne" <lilburne (AT) godzilla (DOT) com> wrote
| Quote: |
Hendrik Belitz wrote:
Jamie Burns wrote:
So is it really better to use typeid() and a C style cast rather than
the
(apparantly) slower dynamic_cast
The best way is not to use that stuff at all. Ask yourself if your
software
design is really good. Most of the time using the RTTI functionality is
only a hint to a bad program design. AFAIK there is only one useful
application of RTTI, and that's emulating weak typing in C++.
Not quite! Lets say I have a class Curve and derived classes
representing line, circular arc, bezier, nurb, composites. And given two
Curves I want to find the points where they intersect. Now I can write
a general method for this, but if I know (RTTI) that the both entities
are lines, or both are arcs, then I can provide a more efficent solution
for these special cases.
|
How about double dispatch - if you're hierarchy is fixed then this is the
cleanest way.
class Curve
{
protected:
// derived classes override these with efficient impl
virtual XXX intersect2(const Line&) const = 0;
virtual XXX intersect2(const Bezier&) const = 0;
//etc etc
public:
// all the derived classes implement intersect EXACTLY the same
virtual XXX intersect(const Curve& other) const
{
return other.intersect2(*this);
}
};
class Bezier : public Curve { .....}
etc
Bezier bez;
Line line;
Curve& c1 = bez;
Curve& c2 = line;
c1.intersect(c2);
calls Bezier::intersect(const Curve&)
calls Line::intersect2(const Bezier&)
does efficient intersection
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|