2010-10-29 38 views
35

在阅读问题之前:
这个问题不是关于如何使用dynamic_cast。它只是关于它的表现。dynamic_cast的性能?

我最近开发了一个设计,其中dynamic_cast用于很多。
当与同事讨论时,几乎所有人都说dynamic_cast不应该使用,因为它的表现不好(这些人是不同背景的同事,在某些情况下彼此不认识,我在大公司)

我决定测试这种方法的性能,而不是仅仅相信它们。

下面的代码用于:

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; 

上述代码使用从boost::date_time Linux上的方法,以得到有用的值。
我在一次执行中完成了3个dynamic_cast,测量它们的代码是相同的。

1所执行的结果如下:
Cast1持续74微秒
硬脂酸钙持续:2微秒
CAST3持续:1微秒

第一铸造总是把74-111微秒,以下在同样的执行中投了1-3微秒。

因此最后我的问题:
dynamic_cast真的表现不好吗?
根据测试结果它没有。我的测试代码是否正确?
为什么这么多开发者认为如果它不是很慢呢?

+13

我错过了什么吗?我看不到cast2或cast3的任何代码。 – Flexo 2010-10-29 10:17:24

+4

谁能说什么不好?你的程序的表现是否足够好?如果是这样,那么表现并不差。动态总时间是否会占用执行时间的很大一部分?如果不是,那么首先担心其他事情。更一般地说,对于某些应用程序来说,74微秒的速度非常慢 - 在我上一份工作中,我已经收到并解析了股票交易所的整个更新记录,更新了数据库,并在一半时间内向客户端应用程序通知了它。如果你有兴趣,然后将其与其他方式进行比较,以获得相同的行为。 – 2010-10-29 10:27:23

+3

在代码中有很多dynamic_casts是设计问题的一个明确标志。 – 2010-10-29 11:07:44

回答

42

首先,您需要测量性能而不仅仅是几次迭代,因为结果将由定时器的分辨率决定。尝试100万以上,以建立一个有代表性的图片。此外,除非您将其与某些事物进行比较,即做相同的事情,但没有动态投射,这一结果就没有意义。其次,您需要确保编译器不会通过优化同一指针上的多个动态强制转换(因此使用循环,但每次使用不同的输入指针),从而不会给您提供错误的结果。

动态转换将会变慢,因为它需要访问对象的RTTI(运行时类型信息)表,并检查转换是否有效。然后,为了正确使用它,您需要添加错误处理代码来检查返回的指针是否为NULL。所有这些都需要周期。

我知道你不想谈这个,但“里的dynamic_cast使用了很多设计”可能是你正在做的事情错的指标...

+5

+1,但10K迭代可能是不够的。有一亿比较好。 – sharptooth 2010-10-29 10:38:18

+0

@sharptooth:公平点! – 2010-10-29 10:51:45

+0

@Oliver Charlesworth“...为了正确使用它,您需要添加错误处理代码来检查返回的指针是否为NULL”您提到的检查的类似版本存在于每种找到一个对象的运行时类型,所以这不是一个参数。 – spectre 2015-10-30 09:54:04

24

性能是毫无意义的比较等效的功能。大多数人都说dynamic_cast比较慢,没有与同等行为进行比较。把它们叫出来。换句话说:

如果'工作'不是要求,我可以编写比你的更快的代码。

有多种实现dynamic_cast的方法,有些方法比其他方法快。例如,Stroustrup发表了一篇关于使用primes to improve dynamic_cast的论文。不幸的是,控制你的编译器如何实现强制转换是非常不寻常的,但是如果性能对你真的很重要,那么你可以控制你使用的编译器。

然而,不使用的dynamic_cast将总是比使用更快 - 但如果你实际上并不需要的dynamic_cast,那么就不要使用它!如果您确实需要动态查找,那么会有一些开销,然后您可以比较各种策略。

+4

+1。是的,顺便说一句,每个活着的人最终会死。这并不意味着活着是一个坏主意。 – sharptooth 2010-10-29 10:39:28

4

很抱歉地说这个,但是你的测试对于确定演员阵容是否缓慢无效。微秒分辨率远不够好。我们正在谈论的是一种操作,即使在最坏的情况下,典型PC上的时钟周期不应超过100个时钟周期,或者小于50纳秒。

毫无疑问,动态演员阵容比静态演员阵容或者重新演绎演员阵容要慢,因为在装配层面上,后两者相当于一个任务(非常快,1个时钟刻度的顺序),以及动态转换需要代码去检查对象以确定其实际类型。

我不能说它真的是多么慢,这可能会从编译器到编译器不同,我需要看到为该行代码生成的汇编代码。但正如我所说,每次调用50纳秒是期望合理的上限。

+0

dynamic_cast需要访问RTTI,这将需要周期。 – doron 2010-10-29 10:59:28

16

这里有几个基准:
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倍,而最好的替代执行几乎相同的reinterpret_cast。

我会引用第一篇文章的结论是:

  • dynamic_cast的是什么,但铸造为基本类型慢;该 特定铸造被优化出
  • 继承级别对dynamic_cast的大的影响
  • 成员变量+的reinterpret_cast是
    确定类型最快可靠的方式;然而,当编码时

绝对数字是100纳秒的单个投的数量级上具有较高的大量维护开销
。像74毫秒的值似乎并不接近现实。

+1

他得到的价值是74 usec(微秒),而不是74毫秒(毫秒)。即便如此,它仍然不太现实。 – Ponkadoodle 2012-03-18 20:14:55