typeid() faster than dynamic_cast<>

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Jamie Burns

    typeid() faster than dynamic_cast<>

    Hello,

    I just did a simple benchmark:

    for (xx=0;xx<100000 ;xx++) {
    rDerived* derived = dynamic_cast<rD erived*>(object );
    if (derived) derived->setValue(messa ge.data.message SetInt.value);
    }

    against:

    for (xx=0;xx<100000 ;xx++) {
    if (typeid(object) == typeid(rDerived *)) ((rDerived*)
    object)->setValue(messa ge.data.message SetInt.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.


  • Alf P. Steinbach

    #2
    Re: typeid() faster than dynamic_cast&lt ;&gt;

    On Tue, 27 Jan 2004 20:50:02 -0000, "Jamie Burns" <sephana@email. com> wrote:
    [color=blue]
    >I just did a simple benchmark:
    >
    > for (xx=0;xx<100000 ;xx++) {
    > rDerived* derived = dynamic_cast<rD erived*>(object );
    > if (derived) derived->setValue(messa ge.data.message SetInt.value);
    > }
    >
    >against:
    >
    > for (xx=0;xx<100000 ;xx++) {
    > if (typeid(object) == typeid(rDerived *)) ((rDerived*)
    >object)->setValue(messa ge.data.message SetInt.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<>.[/color]

    In general this is a quality-of-implementation issue. A factor of 94
    for this code seems excessive. To say the least.

    [color=blue]
    >So is it really better to use typeid() and a C style cast rather than the
    >(apparantly) slower dynamic_cast<>?[/color]

    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?

    Comment

    • lilburne

      #3
      Re: typeid() faster than dynamic_cast&lt ;&gt;

      Jamie Burns wrote:
      [color=blue]
      >
      > 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<>?
      >[/color]

      What if rDerived is actually sDerived, which version is
      correct then?

      Comment

      • Pete Becker

        #4
        Re: typeid() faster than dynamic_cast&lt ;&gt;

        Jamie Burns wrote:[color=blue]
        >
        > So is it really better to use typeid() and a C style cast rather than the
        > (apparantly) slower dynamic_cast<>?
        >[/color]

        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)

        Comment

        • Jonathan Turkanis

          #5
          Re: typeid() faster than dynamic_cast&lt ;&gt;

          "Jamie Burns" <sephana@email. com> wrote in message
          news:bv6itc$lci $1$8302bc10@new s.demon.co.uk.. .[color=blue]
          > Hello,
          >
          > I just did a simple benchmark:
          >
          > for (xx=0;xx<100000 ;xx++) {
          > rDerived* derived = dynamic_cast<rD erived*>(object );
          > if (derived) derived->setValue(messa ge.data.message SetInt.value);
          > }
          >
          > against:
          >
          > for (xx=0;xx<100000 ;xx++) {
          > if (typeid(object) == typeid(rDerived *)) ((rDerived*)
          > object)->setValue(messa ge.data.message SetInt.value);
          > }
          >[/color]

          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




          Comment

          • David White

            #6
            Re: typeid() faster than dynamic_cast&lt ;&gt;

            "Jamie Burns" <sephana@email. com> wrote in message
            news:bv6itc$lci $1$8302bc10@new s.demon.co.uk.. .[color=blue]
            > Hello,
            >
            > I just did a simple benchmark:
            >
            > for (xx=0;xx<100000 ;xx++) {
            > rDerived* derived = dynamic_cast<rD erived*>(object );
            > if (derived) derived->setValue(messa ge.data.message SetInt.value);
            > }
            >
            > against:
            >
            > for (xx=0;xx<100000 ;xx++) {
            > if (typeid(object) == typeid(rDerived *)) ((rDerived*)
            > object)->setValue(messa ge.data.message SetInt.value);
            > }
            >
            > And the latter case blew the former out of the water. Using typeid() with[/color]
            a[color=blue]
            > C style cast was 94 times faster than using dynamic_cast<>.[/color]

            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.
            [color=blue]
            > So is it really better to use typeid() and a C style cast rather than the
            > (apparantly) slower dynamic_cast<>?[/color]

            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



            Comment

            • Andrey Tarasevich

              #7
              Re: typeid() faster than dynamic_cast&lt ;&gt;

              Jonathan Turkanis wrote:[color=blue][color=green]
              >> ...
              >> I just did a simple benchmark:
              >>
              >> for (xx=0;xx<100000 ;xx++) {
              >> rDerived* derived = dynamic_cast<rD erived*>(object );
              >> if (derived) derived->setValue(messa ge.data.message SetInt.value);
              >> }
              >>
              >> against:
              >>
              >> for (xx=0;xx<100000 ;xx++) {
              >> if (typeid(object) == typeid(rDerived *)) ((rDerived*)
              >> object)->setValue(messa ge.data.message SetInt.value);
              >> }
              >>[/color]
              >
              > 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*.
              > ...[/color]

              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

              Comment

              • Pete Becker

                #8
                Re: typeid() faster than dynamic_cast&lt ;&gt;

                Andrey Tarasevich wrote:[color=blue]
                >
                > Jonathan Turkanis wrote:[color=green][color=darkred]
                > >> ...
                > >> I just did a simple benchmark:
                > >>
                > >> for (xx=0;xx<100000 ;xx++) {
                > >> rDerived* derived = dynamic_cast<rD erived*>(object );
                > >> if (derived) derived->setValue(messa ge.data.message SetInt.value);
                > >> }
                > >>
                > >> against:
                > >>
                > >> for (xx=0;xx<100000 ;xx++) {
                > >> if (typeid(object) == typeid(rDerived *)) ((rDerived*)
                > >> object)->setValue(messa ge.data.message SetInt.value);
                > >> }
                > >>[/color]
                > >
                > > 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*.
                > > ...[/color]
                >
                > 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 ))
                > ...
                >[/color]

                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)

                Comment

                • Hendrik Belitz

                  #9
                  Re: typeid() faster than dynamic_cast&lt ;&gt;

                  Jamie Burns wrote:
                  [color=blue]
                  > So is it really better to use typeid() and a C style cast rather than the
                  > (apparantly) slower dynamic_cast<>?[/color]

                  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

                  Comment

                  • lilburne

                    #10
                    Re: typeid() faster than dynamic_cast&lt ;&gt;



                    Hendrik Belitz wrote:[color=blue]
                    > Jamie Burns wrote:
                    >
                    >[color=green]
                    >>So is it really better to use typeid() and a C style cast rather than the
                    >>(apparantly ) slower dynamic_cast<>?[/color]
                    >
                    >
                    > 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++.
                    >[/color]

                    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.

                    Comment

                    • Klaus Nowikow

                      #11
                      Re: typeid() faster than dynamic_cast&lt ;&gt;

                      Hendrik Belitz wrote:[color=blue]
                      > Jamie Burns wrote:
                      >
                      >[color=green]
                      >>So is it really better to use typeid() and a C style cast rather than the
                      >>(apparantly ) slower dynamic_cast<>?[/color]
                      >
                      >
                      > 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++.[/color]

                      Well, I don't think dynamic_cast<>i ng 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

                      Comment

                      • Nick Hounsome

                        #12
                        Re: typeid() faster than dynamic_cast&lt ;&gt;


                        "lilburne" <lilburne@godzi lla.com> wrote in message
                        news:bv7v5a$or2 24$1@ID-179504.news.uni-berlin.de...[color=blue]
                        >
                        >
                        > Hendrik Belitz wrote:[color=green]
                        > > Jamie Burns wrote:
                        > >
                        > >[color=darkred]
                        > >>So is it really better to use typeid() and a C style cast rather than[/color][/color][/color]
                        the[color=blue][color=green][color=darkred]
                        > >>(apparantly ) slower dynamic_cast<>[/color]
                        > >
                        > >
                        > > The best way is not to use that stuff at all. Ask yourself if your[/color][/color]
                        software[color=blue][color=green]
                        > > 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++.
                        > >[/color]
                        >
                        > 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.
                        >[/color]

                        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(cons t Line&) const = 0;
                        virtual XXX intersect2(cons t Bezier&) const = 0;
                        //etc etc
                        public:
                        // all the derived classes implement intersect EXACTLY the same
                        virtual XXX intersect(const Curve& other) const
                        {
                        return other.intersect 2(*this);
                        }
                        };

                        class Bezier : public Curve { .....}
                        etc

                        Bezier bez;
                        Line line;
                        Curve& c1 = bez;
                        Curve& c2 = line;
                        c1.intersect(c2 );
                        calls Bezier::interse ct(const Curve&)
                        calls Line::intersect 2(const Bezier&)
                        does efficient intersection


                        Comment

                        Working...