也许这些数字可以帮助您了解。
我使用以下内容进行了快速测试:
GCC Clock() + XCode的Profiler。
100,000,000个循环迭代。
2 x 2.66 GHz 双核Intel Xeon。
所涉及的类派生自一个基类。
typeid().name()返回“N12fastdelegate13FastDelegate1IivEE”。
测试了5种情况:
1) dynamic_cast< FireType* >( mDelegate )
2) typeid( *iDelegate ) == typeid( *mDelegate )
3) typeid( *iDelegate ).name() == typeid( *mDelegate ).name()
4) &typeid( *iDelegate ) == &typeid( *mDelegate )
5) {
fastdelegate::FastDelegateBase *iDelegate;
iDelegate = new fastdelegate::FastDelegate1< t1 >;
typeid( *iDelegate ) == typeid( *mDelegate )
}
5 只是我实际的代码,因为我需要在检查是否与我已经拥有的对象相似之前创建该类型的一个对象。
未优化
运行结果如下(我对几次运行取了平均值):
1) 1,840,000 Ticks (~2 Seconds) - dynamic_cast
2) 870,000 Ticks (~1 Second) - typeid()
3) 890,000 Ticks (~1 Second) - typeid().name()
4) 615,000 Ticks (~1 Second) - &typeid()
5) 14,261,000 Ticks (~23 Seconds) - typeid() with extra variable allocations.
因此,结论如下:
- 对于没有优化的简单转换情况,
typeid()
比 dyncamic_cast
快两倍以上。
- 在现代计算机上,两者之间的差异约为1纳秒(一毫秒的百万分之一)。
使用优化(-Os)
1) 1,356,000 Ticks - dynamic_cast
2) 76,000 Ticks - typeid()
3) 76,000 Ticks - typeid().name()
4) 75,000 Ticks - &typeid()
5) 75,000 Ticks - typeid() with extra variable allocations.
因此,结论是:
- 对于简单的转换情况,使用优化后的
typeid()
比使用 dynamic_cast
快近 20 倍。
图表
代码
根据评论的要求,下面是代码(有点凌乱,但可以运行)。'FastDelegate.h' 可以从 这里 获得。
#include <iostream>
#include "FastDelegate.h"
#include "cycle.h"
#include "time.h"
#define CAST
class ZoomManager
{
public:
template < class Observer, class t1 >
void Subscribe( void *aObj, void (Observer::*func )( t1 a1 ) )
{
mDelegate = new fastdelegate::FastDelegate1< t1 >;
std::cout << "Subscribe\n";
Fire( true );
}
template< class t1 >
void Fire( t1 a1 )
{
fastdelegate::FastDelegateBase *iDelegate;
iDelegate = new fastdelegate::FastDelegate1< t1 >;
int t = 0;
ticks start = getticks();
clock_t iStart, iEnd;
iStart = clock();
typedef fastdelegate::FastDelegate1< t1 > FireType;
for ( int i = 0; i < 100000000; i++ ) {
#ifdef CAST
if ( dynamic_cast< FireType* >( mDelegate ) )
#else
if ( typeid( *iDelegate ) == typeid( *mDelegate ) )
#endif
{
t++;
} else {
t--;
}
}
iEnd = clock();
printf("Clock ticks: %i,\n", iEnd - iStart );
std::cout << typeid( *mDelegate ).name()<<"\n";
ticks end = getticks();
double e = elapsed(start, end);
std::cout << "Elasped: " << e;
}
template< class t1, class t2 >
void Fire( t1 a1, t2 a2 )
{
std::cout << "Fire\n";
}
fastdelegate::FastDelegateBase *mDelegate;
};
class Scaler
{
public:
Scaler( ZoomManager *aZoomManager ) :
mZoomManager( aZoomManager ) { }
void Sub()
{
mZoomManager->Subscribe( this, &Scaler::OnSizeChanged );
}
void OnSizeChanged( int X )
{
std::cout << "Yey!\n";
}
private:
ZoomManager *mZoomManager;
};
int main(int argc, const char * argv[])
{
ZoomManager *iZoomManager = new ZoomManager();
Scaler iScaler( iZoomManager );
iScaler.Sub();
delete iZoomManager;
return 0;
}