typeid() faster than dynamic_cast<>

Discussion in 'C++' started by Jamie Burns, Jan 27, 2004.

  1. Jamie Burns

    Jamie Burns Guest

    Hello,

    I just did a simple benchmark:

    for (xx=0;xx<100000;xx++) {
    rDerived* derived = dynamic_cast<rDerived*>(object);
    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.
     
    Jamie Burns, Jan 27, 2004
    #1
    1. Advertising

  2. On Tue, 27 Jan 2004 20:50:02 -0000, "Jamie Burns" <> wrote:

    >I just did a simple benchmark:
    >
    > for (xx=0;xx<100000;xx++) {
    > rDerived* derived = dynamic_cast<rDerived*>(object);
    > 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.


    >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?
     
    Alf P. Steinbach, Jan 27, 2004
    #2
    1. Advertising

  3. Jamie Burns

    lilburne Guest

    Jamie Burns wrote:

    >
    > 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?
     
    lilburne, Jan 27, 2004
    #3
  4. Jamie Burns

    Pete Becker Guest

    Jamie Burns wrote:
    >
    > 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)
     
    Pete Becker, Jan 27, 2004
    #4
  5. "Jamie Burns" <> wrote in message
    news:bv6itc$lci$1$...
    > Hello,
    >
    > I just did a simple benchmark:
    >
    > for (xx=0;xx<100000;xx++) {
    > rDerived* derived = dynamic_cast<rDerived*>(object);
    > 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
     
    Jonathan Turkanis, Jan 27, 2004
    #5
  6. Jamie Burns

    David White Guest

    "Jamie Burns" <> wrote in message
    news:bv6itc$lci$1$...
    > Hello,
    >
    > I just did a simple benchmark:
    >
    > for (xx=0;xx<100000;xx++) {
    > rDerived* derived = dynamic_cast<rDerived*>(object);
    > 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.

    > 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
     
    David White, Jan 27, 2004
    #6
  7. Jonathan Turkanis wrote:
    >> ...
    >> I just did a simple benchmark:
    >>
    >> for (xx=0;xx<100000;xx++) {
    >> rDerived* derived = dynamic_cast<rDerived*>(object);
    >> 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
     
    Andrey Tarasevich, Jan 28, 2004
    #7
  8. Jamie Burns

    Pete Becker Guest

    Andrey Tarasevich wrote:
    >
    > Jonathan Turkanis wrote:
    > >> ...
    > >> I just did a simple benchmark:
    > >>
    > >> for (xx=0;xx<100000;xx++) {
    > >> rDerived* derived = dynamic_cast<rDerived*>(object);
    > >> 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)
     
    Pete Becker, Jan 28, 2004
    #8
  9. 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++.

    --
    To get my real email adress, remove the two onkas
    --
    Dipl.-Inform. Hendrik Belitz
    Central Institute of Electronics
    Research Center Juelich
     
    Hendrik Belitz, Jan 28, 2004
    #9
  10. Jamie Burns

    lilburne Guest

    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.
     
    lilburne, Jan 28, 2004
    #10
  11. 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++.


    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
     
    Klaus Nowikow, Jan 28, 2004
    #11
  12. "lilburne" <> wrote in message
    news:bv7v5a$or224$-berlin.de...
    >
    >
    > 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
     
    Nick Hounsome, Jan 29, 2004
    #12
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Dave Theese

    typeid and polymorphic classes

    Dave Theese, Sep 8, 2003, in forum: C++
    Replies:
    5
    Views:
    563
    Govindan
    Sep 8, 2003
  2. Andreas Sch.

    typeid and dynamic_cast, gcc 3.3

    Andreas Sch., Jan 23, 2004, in forum: C++
    Replies:
    18
    Views:
    1,887
    Janusz Szpilewski
    Jan 29, 2004
  3. Mike

    RTTI typeid question

    Mike, May 28, 2004, in forum: C++
    Replies:
    3
    Views:
    3,970
  4. steve
    Replies:
    17
    Views:
    701
    Mike Smith
    Sep 13, 2004
  5. flopbucket

    dynamic_cast and typeid

    flopbucket, Aug 15, 2007, in forum: C++
    Replies:
    4
    Views:
    535
Loading...

Share This Page