虚拟继承的性能影响
我正在考虑在实时应用程序中使用虚拟继承。使用虚拟继承是否会对性能产生类似于调用虚拟函数的性能影响?有问题的对象只会在启动时创建,但我担心层次结构中的所有函数是否都会通过 vtable 分派,或者是否只有来自虚拟基类的函数才会分派。
I am considering using virtual inheritance in a real-time application. Does using virtual inheritance have a performance impact similar to that of calling a virtual function? The objects in question would only be created at start up but I'm concerned if all functions from the hierarchy would be dispatched via a vtable or if only those from the virtual base class would be.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
常见的实现将使用额外的间接访问来访问虚拟基类的数据成员。
正如 James 在评论中指出的那样,在多重继承场景中调用基类的成员函数将需要调整 this 指针,如果该基类是虚拟的,则基类的偏移量派生类对象中的类子对象取决于派生类的动态类型,并且需要在运行时计算。
这是否对现实世界的应用程序有任何明显的性能影响取决于很多因素:
虚拟基地是否有数据成员?通常,需要从虚拟派生抽象基类,并且具有任何数据成员的抽象基类通常都具有代码味道。
假设您拥有包含数据成员的虚拟基地,这些数据是否在关键路径中被访问?如果用户单击 GUI 中的某个按钮会导致几十个额外的间接访问,则没有人会注意到。
如果避免虚拟基地,替代方案会是什么?该设计不仅可能较差,而且替代设计也可能会对性能产生影响。毕竟,它必须实现与 TANSTAAFL 相同的目标。然后你用一种性能损失换取另一种性能损失加上劣质的设计。
附加说明:查看 Stan Lippmann 的Inside the C++ Object Model ,它相当彻底地回答了这些问题。
Common implementations will make access to data members of virtual base classes use an additional indirection.
As James points out in his comments, calling a member function of a base class in a multiple inheritance scenario will need adjustment of the
this
pointer, and if that base class is virtual, then the offset of the base class sub-object in the derived class's object depends on the dynamic type of the derived class and will need to be calculated at runtime.Whether this has any visible performance impact on real-world applications depends on many things:
Do virtual bases have data members at all? Often, it's abstract base classes that need to be derived from virtually, and abstract bases that have any data members are often a code smell anyway.
Assuming you have virtual bases with data members, are those accessed in a critical path? If a user clicking on some button in a GUI results in a few dozen additional indirections, nobody will notice.
What would be the alternative if virtual bases are avoided? Not only might the design be inferior, it is also likely that the alternative design has a performance impact, too. It has to achieve the same goal, after all, and TANSTAAFL. Then you traded one performance loss for another plus an inferior design.
Additional note: Have a look at Stan Lippmann's Inside the C++ Object Model, which answers such questions quite thoroughly.
看看下面发表的 OOPSLA'96 大规模实验研究。我复制粘贴 bibtex 条目、摘要和论文链接。我认为这是迄今为止关于该主题的最全面的实验研究。
摘要:
我们研究虚函数的直接成本
在 C++ 程序中调用,假设标准
使用虚函数表实现。我们
通过实验测量这一开销
大型基准程序,结合使用
可执行检查和处理器模拟。我们的
结果表明,所测量的 C++ 程序花费了
中位数为 5.2% 的时间和 3.7% 的时间
调度代码中的说明。对于“所有虚拟”
程序的版本中,中位开销上升到
13.7%(指令的 13%)。 “thunk”变体
虚函数表实现的减少
相对于平均开销 21%
标准实施。在未来的处理器上,这些
管理费用可能会适度增加
http://www.cs.ucsb。 edu/~urs/oocsb/papers/oopsla96.pdf
Take a look at the following large scale experimental study published OOPSLA'96. I am copy pasting a bibtex entry, the abstract and a link to the paper. I would consider this the most comprehensive experimental study on the topic to date.
Abstract:
We study the direct cost of virtual function
calls in C++ programs, assuming the standard
implementation using virtual function tables. We
measure this overhead experimentally for a number of
large benchmark programs, using a combination of
executable inspection and processor simulation. Our
results show that the C++ programs measured spend a
median of 5.2% of their time and 3.7% of their
instructions in dispatch code. For “all virtuals”
versions of the programs, the median overhead rises to
13.7% (13% of the instructions). The “thunk” variant
of the virtual function table implementation reduces
the overhead by a median of 21% relative to the
standard implementation. On future processors, these
overheads are likely to increase moderately
http://www.cs.ucsb.edu/~urs/oocsb/papers/oopsla96.pdf
你确定你说的是虚拟继承吗?如果是这样,它与普通虚拟函数调用的成本相同。 vtable链式搜索只遵循指定的路径。
你说这是在启动时。您的磁盘开销(仅将代码加载到内存中)可能需要比用于 vtable 查找的半打指令多几个数量级的时间。如果您能对此进行分析并发现差异,我会感到有点惊讶。
Are you sure you mean virtual inheritance? If so, it's identical to the cost of a normal virtual function call. The vtable chained search just follows a specified path.
You said that this was at startup. Your disk overhead (from simply loading your code into memory) is likely to require orders of magnitude more time than the half-dozen instructions or so for vtable lookups. I'd be somewhat surprised if you could profile this and detect a difference.
在不检查编译或运行时细节的情况下,根据我使用 GNU C++17 的测试,访问虚拟基类中的数据成员对性能没有影响。
Without inspecting compilation or runtime details, based on my test using GNU C++17, accessing data member in virtual base class has no performance inpact.