One of the first references I found on the web indicated the virtual-function-then-cast approach being up to 20x faster.
http://www.nerdblog.com/2006/12/how-slow-is-dynamiccast.html
That reference didn't provide code, so I wrote a quick test with the hierarchy of following classes:
ClassA, ClassB: public ClassA, and ClassC: public ClassB.
My tests suggest that this approach is about 5x faster when compiled with g++ -O3 (same speed with no optimization). For my application dynamic_cast should be perfectly fine.
Times for 3*100 million cast and function evaluations (in a smidge more than trivial loop)
Not optimized:
mycast 0m13.879s
dynamic_cast 0m0.060s
Optimized
mycast 0m0.919s
dynamic_cast 0m4.729s
a.h
class AClassA{
public:
static const int flag = 0x1;
AClassA(){}
virtual ~AClassA(){}
virtual int name() const ;
int a(){return 1;}
};
class BClassB: public AClassA {
public:
static const int flag = 0x2;
BClassB(){}
virtual ~BClassB(){}
int name() const ;
int b(){return 2;}
};
class CClassC: public BClassB {
public:
static const int flag = 0x4;
CClassC(){}
virtual ~CClassC(){}
int name() const ;
int c(){return 3;}
};
a.cc
#include "a.h"
#ifdef use_mycast
#warning "using mycast"
#define caster mycast
#define extras
#else
#define caster dynamic_cast
#define extras *
#endif
int AClassA::name() const {return AClassA::flag;}
int BClassB::name() const {return AClassA::flag | BClassB::flag;}
int CClassC::name() const {return AClassA::flag | BClassB::flag | CClassC::flag;}
template
T * mycast(AClassA * a){
if(a->name() & T::flag)return (T*)a;
}
int func_dcast(AClassA * a){
CClassC * c = caster(a);
if(c)return c->c();
else {
BClassB * b = caster(a);
if(b)return b->b();
}
return a->a();
}
int main(int ac, char * av[]){
const int ntrials = 100000000;
int sums[8] = {0,0,0,0};
AClassA a;
BClassB b;
CClassC c;
for(int i=0; i!=ntrials; i++){
sums[func_dcast(&a)]++;
sums[func_dcast(&b)]++;
sums[func_dcast(&c)]++;
}
printf("%d %d %d %d\n", sums[0], sums[1], sums[2], sums[3]);
return 0;
}
makefile
all:
g++ a.cc -Duse_mycast -o mycast.opt -O3 -fno-rtti
g++ a.cc -Duse_mycast -o mycast -fno-rtti
g++ a.cc -o dcast.opt -O3
g++ a.cc -o dcast
test.sh
echo "Unoptimized (mycast then dcast)"
time ./mycast | grep real
time ./dcast | grep real
echo "Optimimzed (mycast then dcast)"
time ./mycast.opt | grep real
time ./dcast.opt | grep real
No comments:
Post a Comment