I wrote a simple example, which estimates average time of calling virtual function, using base class interface and dynamic_cast and call of non-virtual function. Here is it:
#include <iostream>
#include <numeric>
#include <list>
#include <time.h>
#define CALL_COUNTER (3000)
__forceinline int someFunction()
{
return 5;
}
struct Base
{
virtual int virtualCall() = 0;
virtual ~Base(){};
};
struct Derived : public Base
{
Derived(){};
virtual ~Derived(){};
virtual int virtualCall(){ return someFunction(); };
int notVirtualCall(){ return someFunction(); };
};
struct Derived2 : public Base
{
Derived2(){};
virtual ~Derived2(){};
virtual int virtualCall(){ return someFunction(); };
int notVirtualCall(){ return someFunction(); };
};
typedef std::list<double> Timings;
Base* createObject(int i)
{
if(i % 2 > 0)
return new Derived();
else
return new Derived2();
}
void callDynamiccast(Timings& stat)
{
for(unsigned i = 0; i < CALL_COUNTER; ++i)
{
Base* ptr = createObject(i);
clock_t startTime = clock();
for(int j = 0; j < CALL_COUNTER; ++j)
{
Derived* x = (dynamic_cast<Derived*>(ptr));
if(x) x->notVirtualCall();
}
clock_t endTime = clock();
double callTime = (double)(endTime - startTime) / CLOCKS_PER_SEC;
stat.push_back(callTime);
delete ptr;
}
}
void callVirtual(Timings& stat)
{
for(unsigned i = 0; i < CALL_COUNTER; ++i)
{
Base* ptr = createObject(i);
clock_t startTime = clock();
for(int j = 0; j < CALL_COUNTER; ++j)
ptr->virtualCall();
clock_t endTime = clock();
double callTime = (double)(endTime - startTime) / CLOCKS_PER_SEC;
stat.push_back(callTime);
delete ptr;
}
}
int main()
{
double averageTime = 0;
Timings timings;
timings.clear();
callDynamiccast(timings);
averageTime = (double) std::accumulate<Timings::iterator, double>(timings.begin(), timings.end(), 0);
averageTime /= timings.size();
std::cout << "time for callDynamiccast: " << averageTime << std::endl;
timings.clear();
callVirtual(timings);
averageTime = (double) std::accumulate<Timings::iterator, double>(timings.begin(), timings.end(), 0);
averageTime /= timings.size();
std::cout << "time for callVirtual: " << averageTime << std::endl;
return 0;
}
It looks like callDynamiccast takes almost two times more.
time for callDynamiccast: 0.000240333
time for callVirtual: 0.0001401
Any ideas why does it?
EDITED: object creation is made in separete function now, so the compler does not know it real type. Almost the same result.
EDITED2: create two different types of a derived objects.
ptr
really points to aDerived
object. – Johannes Schaub - litbBase* createBase()
which randomly returnsBase*
orDerived*
and call it in each loop iteration. – ipc