dynamic_cast的性能?
在阅读这个问题之前:
这个问题不是关于如何使用dynamic_cast
有用的。 它只是关于它的performance。
我最近开发了一个dynamic_cast
被广泛使用的devise。
当与同事讨论时,几乎每个人都说dynamic_cast
不应该被使用,因为它的performance不好(这些都是不同背景的同事,在某些情况下彼此不认识,我在一家大公司工作)
我决定testing这种方法的性能,而不是仅仅相信它们。
以下代码被使用:
ptime firstValue( microsec_clock::local_time() ); ChildObject* castedObject = dynamic_cast<ChildObject*>(parentObject); ptime secondValue( microsec_clock::local_time() ); time_duration diff = secondValue - firstValue; std::cout << "Cast1 lasts:\t" << diff.fractional_seconds() << " microsec" << std::endl;
上面的代码使用来自Linux上boost::date_time
方法来获取可用的值。
我在一次执行中完成了3个dynamic_cast
,测量它们的代码是相同的。
1次执行的结果如下:
Cast1持续:74微秒
Cast2持续:2微秒
Cast3持续:1微秒
第一个演员总是拿着74-111微秒,下面的演员在同样的执行下拿了1-3微秒。
所以最后我的问题是:
dynamic_cast
真的performance不好吗?
根据testing结果它不是。 我的testing代码是否正确?
为什么这么多的开发人员认为,如果不是这样,速度会变慢呢?
首先,你需要测量性能,而不仅仅是几次迭代,因为你的结果将由定时器的分辨率决定。 尝试一百万+,以build立一个有代表性的图片。 而且,这个结果是没有意义的,除非你把它与某些东西进行比较,即做同样的事情,但没有dynamic的投射。
其次,你需要确保编译器没有给你错误的结果,优化了同一个指针上的多个dynamic转换(所以使用循环,但每次使用不同的input指针)。
dynamic转换会比较慢,因为它需要访问对象的RTTI(运行时types信息)表,并检查转换是否有效。 然后,为了正确使用它,您将需要添加error handling代码来检查返回的指针是否为NULL
。 所有这些都需要周期。
我知道你不想谈论这个,但是“dynamic_cast被大量使用的devise”可能是你做错事的一个指标。
没有比较等效function,性能没有意义。 大多数人说,dynamic_cast比较慢,没有比较相同的行为。 把它们叫出来。 换一种方式:
如果“工作”不是必需的,我可以编写比你的代码更快的代码。
有多种实现dynamic_cast的方式,有些比其他更快。 例如,Stroustrup发表了一篇关于使用素数来改进dynamic_cast的论文。 不幸的是,控制你的编译器如何实现转换是非常不寻常的,但是如果性能真的对你很重要,那么你可以控制你使用的编译器。
但是, 不使用 dynamic_cast 总是会比使用 dynamic_cast更快 – 但是如果您实际上不需要dynamic_cast,则不要使用它! 如果您确实需要dynamic查找,那么会有一些开销,然后您可以比较各种策略。
这里有几个基准:
http://tinodidriksen.com/2010/04/14/cpp-dynamic-cast-performance/
http://www.nerdblog.com/2006/12/how-slow-is-dynamiccast.html
据他们说,dynamic_cast比reinterpret_cast慢5-30倍,最好的select与reinterpret_cast差不多。
我会引用第一篇文章的结论:
- dynamic_cast对于任何东西都很慢,除了强制转换为基types; 该特定的演员被优化了
- inheritance层次对dynamic_cast有很大的影响
- 成员variables+ reinterpret_cast是最快可靠的方式
确定types; 然而,这有更多的维护开销
编码时
绝对数字大约在100纳秒的单个演员。 像74毫秒的值似乎并不接近现实。
对不起,这样说,但你的testing几乎是无用的,以确定演员是否缓慢或没有。 微秒的分辨率远不够好。 我们正在讨论的是,即使在最糟糕的情况下,一个典型的PC上也不应该超过100个时钟周期,或者不到50纳秒。
毫无疑问,dynamic演员阵容比静态演员阵容或者重新演绎演员阵容要慢,因为在assembly层面上,后两者相当于一个任务(非常快,1个时钟周期的顺序),dynamic演员阵容需要代码去检查对象来确定它的实际types。
我不能说它真的有多慢,这可能会从编译器到编译器不同,我需要看到为该行代码生成的汇编代码。 但是,正如我所说,每次调用50纳秒是期望合理的上限。