Performance of dynamic_cast?

前端 未结 5 1905
天命终不由人
天命终不由人 2020-11-29 05:30

Before reading the question:
This question is not about how useful it is to use dynamic_cast. Its just about its performance.

I\'ve recently develop

5条回答
  •  夕颜
    夕颜 (楼主)
    2020-11-29 06:28

    Your mileage may vary, to understate the situation.

    The performance of dynamic_cast depends a great deal on what you are doing, and can depend on what the names of classes are (and, comparing time relative to reinterpet_cast seems odd, since in most cases that takes zero instructions for practical purposes, as does e.g. a cast from unsigned to int).

    I've been looking into how it works in clang/g++. Assuming that you are dynamic_casting from a B* to a D*, where B is a (direct or indirect) base of D, and disregarding multiple-base-class complications, It seems to work by calling a library function which does something like this:

    for dynamic_cast(  p  )   where p is B*
    
    type_info const * curr_typ = &typeid( *p );
    while(1) {
         if( *curr_typ == typeid(D)) { return static_cast(p); } // success;
         if( *curr_typ == typeid(B)) return nullptr;   //failed
         curr_typ = get_direct_base_type_of(*curr_typ); // magic internal operation
    }
    

    So, yes, it's pretty fast when *p is actually a D; just one successful type_info compare. The worst case is when the cast fails, and there are a lot of steps from D to B; in this case there are a lot of failed type comparisons.

    How long does type comparison take? it does this, on clang/g++:

    compare_eq( type_info const &a, type_info const & b ){
       if( &a == &b) return true;   // same object
       return strcmp( a.name(), b.name())==0;
    }
    

    The strcmp is needed since it's possible to have two different type_info objects representing the same type (although I'm pretty sure this only happens when one is in a shared library, and the other is not in that library). But, in most cases, when types are actually equal, they reference the same type_info; thus most successful type comparisons are very fast.

    The name() method just returns a pointer to a fixed string containing the mangled name of the class. So there's another factor: if many of the classes on the way from D to B have names starting with MyAppNameSpace::AbstractSyntaxNode<, then the failing compares are going to take longer than usual; the strcmp won't fail until it reaches a difference in the mangled type names.

    And, of course, since the operation as a whole is traversing a bunch of linked data structures representing the type hierarchy, the time will depend on whether those things are fresh in the cache or not. So the same cast done repeatedly is likely to show an average time which doesn't necessarily represent the typical performance for that cast.

提交回复
热议问题