我必须设计和开发一个将在实时环境中使用的C++模块(它将在现代多核PC上运行).当我设计它时,我创建了C++接口(只有纯虚拟成员函数的类),我使用依赖注入,以便能够使用Google Mock Framework进行测试.我知道这种方法的运行时性能开销与静态绑定有关,但可测试性是一个重要因素.
我认为我们可以在开发期间测量执行时间,并在集成阶段运行测试以确定性能开销是否可接受.
在过去的几天里,我收到批评者称这种方法不起作用,因为后期绑定具有不确定性.这种非确定性本质意味着即使我测试它并且我测量执行时间,之后,在生产环境中,执行时间可能更多只是因为后期绑定(因为我使用了纯虚函数).
据我所知,这是不可能的(除了缓存未命中和类似的东西).如果使用接口,则意味着您将有一些额外的间接层,并且编译器在某些情况下无法优化(例如内联函数),但就是这样.
所以我的问题不是性能开销,而是性能的可变性.它可以在两次执行之间变化吗?
我找不到关于这个主题的任何文章或基准.找到的文章对静态和动态绑定之间的恒定性能差异进行了基准测试,但现在又不是问题.
如果您知道任何可公开访问的文章,网页,书籍,来源或任何可以提供帮助的内容,请与我分享.
谢谢!
更新: 我想把链接和文件放在我找到答案的地方:
虚函数调用的工作原理:Parashift C++ FAQ
有关C++性能的技术报告,第87页:"如果可以在编译时确定对象的静态类型,则调用虚函数可能不比调用非虚成员函数更昂贵.如果必须动态确定类型在运行时,每次呼叫的开销通常都是固定数量的机器指令(§5.3.3)."
Agnes Fog的C++优化软件:适用于Windows,Linux和Mac平台的优化指南,第53页:"调用虚拟成员函数所需的时间比调用非虚拟成员函数要多几个时钟周期,只要函数调用语句总是调用相同版本的虚函数."
Cheers and h.. 14
2005年,国际C++标准化委员会发布了一份关于C++性能的技术报告,我认为该报告有资格作为该主题的文章和基准.
简短的回答是缓存未命中可以显着影响运行时间,并且在虚拟函数的调用中,(通常)咨询vtable.
但实际上(与正式相反),就执行的机器代码而言,每次调用的开销是固定的,因为所有现有的编译C++实现都使用vtable.您可以在不影响呼叫开销的情况下为您的内容派生类.任何调用仍然执行(1)在对象的已知位置查找vtable指针,(2)在vtable中的已知位置查找函数地址,(3)调用该函数,除非编译器知道函数指针可用于例如早期的通话,只要有任何话,就可以让通话变得更快.