C ++纯虚函数调用的性能可变性

时间:2013-12-07 07:53:49

标签: c++ performance polymorphism virtual-functions

我必须设计和开发一个将在实时环境中使用的C ++模块(它将在现代多核PC上运行)。当我设计它时,我创建了C ++接口(只有纯虚拟成员函数的类),我使用依赖注入,以便能够使用Google Mock Framework进行测试。我知道这种方法的运行时性能开销与静态绑定有关,但可测试性是一个重要因素。

我认为我们可以在开发过程中测量执行时间,并在集成阶段运行测试,以确定性能开销是否可以接受。

在过去的几天里,我收到批评者称这种方法不起作用,因为后期绑定具有不确定性。这种非确定性本质意味着即使我测试它并测量执行时间,之后,在生产环境中,执行时间可能更多只是因为后期绑定(因为我使用了纯虚函数)。

据我所知,这是不可能的(除了缓存未命中和类似的东西)。如果使用接口,则意味着您将有一些额外的间接层,并且编译器在某些情况下无法优化(例如内联函数),但就是这样。

所以我的问题不是性能开销,而是性能的可变性。它可以在两次执行之间变化吗?

我找不到关于此主题的任何文章或基准。找到的文章对静态和动态绑定之间的恒定性能差异进行了基准测试,但现在不再是问题了。

如果您知道任何可公开访问的文章,网页,图书,来源或任何可以提供帮助的内容,请与我分享。

谢谢!

更新 我想把链接和文件放在我找到答案的地方:

  1. 虚拟函数调用的工作原理:Parashift C++ FAQ
  2. Technical Report on C++ Performance,第87页:“如果可以在编译时确定对象的静态类型,则调用虚函数可能不比调用非虚成员函数贵。如果类型必须在运行时动态确定,每次呼叫的开销通常是固定数量的机器指令(第5.3.3节)。“
  3. 艾格尼丝雾的Optimizing software in C++: An optimization guide for Windows, Linux and Mac platforms,53页:“它需要调用一个虚拟成员函数的时间是几个时钟周期超过它需要调用一个非虚拟成员函数,提供始终函数调用语句调用相同版本的虚函数。“

1 个答案:

答案 0 :(得分:14)

2005年国际C ++标准化委员会发布了一个Technical Report on C++ Performance,我认为该文章既有资格也有关于此主题的基准。

简短的回答是缓存未命中会大大影响运行时间,并且在调用虚函数时,通常会查询vtable。

但是在实践中(与正式相反),就执行的机器代码而言,每次调用的开销是已修复,因为所有现有的已编译C ++实现都使用vtable。您可以在不影响呼叫开销的情况下为您的内容派生类。任何调用仍然执行(1)在对象中的已知位置查找vtable指针,(2)在vtable中的已知位置查找函数地址,(3)调用该函数,除非编译器知道函数指针可用于例如一个较早的电话,如果有的话,只是让电话更快一点。