C++纯虚拟函数调用的性能可变性
Performance variability of C++ pure virtual function calls
我不得不设计和开发一个将在实时环境中使用的C++模块(它将在现代多核PC上运行)。当我设计它时,我创建了C++接口(只有纯虚拟成员函数的类),并使用了依赖项注入,以便能够用Google Mock Framework测试它。我知道这种方法的运行时性能开销与静态绑定相当,但可测试性是一个重要因素。
我认为我们可以在开发过程中测量执行时间,也可以在集成阶段运行测试,以确定性能开销是否可以接受。
在过去的几天里,我收到了一些批评,认为这种方法行不通,因为后期绑定具有不确定性。这种不确定性意味着,即使我测试它并测量执行时间,稍后在生产环境中,执行时间可能会更多,这只是因为后期绑定(因为我使用了纯虚拟函数)。
据我所知,这是不可能的(缓存未命中和类似的情况除外)。如果你使用接口,这意味着你将有一些额外的间接层,编译器在某些情况下无法优化(例如内联函数),但仅此而已
所以我的问题不是性能开销,而是性能的可变性。两次执行之间会有所不同吗?
我找不到任何关于这个主题的文章或基准。所发现的文章对静态绑定和动态绑定之间的恒定性能差异进行了基准测试,但现在这不是问题所在。
如果你知道任何可以公开访问的文章、网页、书籍、来源或任何有帮助的东西,请与我分享。
谢谢!
更新:我想把链接和文件放在我找到答案的地方:
- 虚拟函数调用的工作原理:Parashift C++常见问题解答
- 《C++性能技术报告》,第87页:"如果对象的静态类型可以在编译时确定,那么调用虚拟函数可能不会比调用非虚拟成员函数更昂贵。如果类型必须在运行时动态确定,那么每次调用的开销通常是固定数量的机器指令(§5.3.3)。"
- Agnes Fog的C++优化软件:Windows、Linux和Mac平台的优化指南,第53页:"调用虚拟成员函数所需的时间比调用非虚拟成员函数多几个时钟周期,前提是函数调用语句始终调用相同版本的虚拟函数。"
2005年,国际C++标准化委员会发布了一份《C++性能技术报告》,我认为该报告既是关于这一主题的文章,也是关于这一话题的基准。
简单的答案是,缓存未命中会极大地影响运行时间,并且在调用虚拟函数时(通常)会咨询vtable。
但在实践中(与形式上相反),就执行的机器代码而言,每次调用的开销是固定的,因为所有现存的编译C++实现都使用vtables。您可以随心所欲地派生类,而不会影响调用开销。任何调用仍然执行(1)在对象的已知位置查找vtable指针,(2)在vtable的已知位置查询函数地址,(3)调用该函数,除非编译器知道函数指针可以从早期调用中获得,否则这只会使调用更快。
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- OpenMP阵列性能较差
- 递归列出所有目录中的C++与Python与Ruby的性能
- 大小相等但成员数量不同的结构之间的性能差异
- 为什么constexpr的性能比正常表达式差
- 在类中使用随机生成器时出现性能问题
- 在main()之外初始化std::vector会导致性能下降(多线程)
- 海湾合作委员会 ARM 性能下降
- GCC 和 Clang 代码性能的巨大差异
- 在容量内调整矢量大小时的性能影响
- 了解算法的性能差异(如果以不同的编程语言实现)
- 未达到的情况会影响开关外壳性能
- QStringList vs list<shared_ptr<QString>> 性能比较C++
- 是否总是可以将使用递归编写的程序重写为不使用递归的程序C++,性能观点是什么?
- 哪种方法更好,性能明智
- C++ 特征库:引用的性能开销<>
- 与多个 for 循环与单个 for 循环 wrt 相关的性能从多映射获取数据
- 基于范围的 for 循环range_declaration中各种说明符之间的性能差异
- 当为可变性配置时,boost::heap::d_ary_heap 保留的额外 std::list 的目的是什么?
- C++纯虚拟函数调用的性能可变性