![]() |
1
86
一个好的经验法则是:
使用虚拟函数对性能的影响很小,但不太可能影响应用程序的整体性能。在算法和I/O中寻找性能改进的更好地方。 一篇讨论虚拟函数(以及更多)的优秀文章是 Member Function Pointers and the Fastest Possible C++ Delegates . |
![]() |
2
160
你的问题让我很好奇,所以我在3GHz上进行了一些计时,以便我们使用PowerPCCPU。我运行的测试是用get/set函数生成一个简单的4d向量类
然后,我设置了三个数组,每个数组包含1024个这些向量(足够小以适合l1),并运行了一个循环,将它们相互添加(a.x=b.x+c.x)1000次。我用定义为
因此,在这种情况下(所有东西都放在缓存中),虚拟函数调用比内联调用慢20倍。但这到底意味着什么?每次通过回路都会导致
由此我得出结论: 对 ,虚拟函数比直接函数慢得多,并且 不 除非你计划每秒给他们打1000万次电话,否则没关系。 |
![]() |
3
40
当objective-c(所有方法都是虚拟的)是iphone和freakin的主要语言时 爪哇 是Android的主要语言,我认为在我们的3 GHz双核塔上使用C++虚拟功能是相当安全的。 |
![]() |
4
32
在性能非常关键的应用程序(如视频游戏)中,虚拟函数调用可能太慢。对于现代硬件,最大的性能问题是缓存丢失。如果数据不在缓存中,可能需要数百个周期才能使用。 当CPU获取新函数的第一条指令且不在缓存中时,正常的函数调用可能会生成指令缓存未命中。 虚拟函数调用首先需要从对象加载vtable指针。这可能导致数据缓存未命中。然后它从vtable加载函数指针,这可能导致另一个数据缓存未命中。然后它调用函数,这会导致指令缓存丢失,就像非虚拟函数一样。 在许多情况下,两个额外的缓存未命中不是一个问题,但是在性能关键的代码上,通过一个紧密的循环,它可以显著降低性能。 |
![]() |
5
27
从第44页 Agner Fog's "Optimizing Software in C++" manual :
|
![]() |
6
6
当然。当计算机以100MHz运行时,这是一个问题,因为在调用vtable之前,每个方法调用都需要查找它。但是今天…在3GHz的CPU上,第一级缓存的内存比我的第一台计算机多?一点也不。从主RAM分配内存将比所有函数都是虚拟的花费更多的时间。 就像以前人们说结构化编程很慢的时候,因为所有的代码都被分解成函数,每个函数都需要堆栈分配和函数调用! 唯一一次我会考虑考虑虚拟函数的性能影响的时候,是如果它被大量使用,并以模板化的代码进行实例化,最终在所有事情中结束。即使那样,我也不会花太多精力去做! PS想到了其他“易于使用”的语言——他们所有的方法都是虚拟的,而且现在他们不爬行。 |
![]() |
7
6
除了执行时间,还有另一个性能标准。vtable也占用内存空间,在某些情况下可以避免:atl使用编译时” simulated dynamic binding 用 templates 要得到“静态多态性”的效果,这有点难以解释;您基本上将派生类作为参数传递给基类模板,因此在编译时,基类“知道”其派生类在每个实例中是什么。不会让您将多个不同的派生类存储在一个基类型集合中(这是运行时多态性),但从静态意义上讲,如果您想使一个类Y与一个先前存在的模板类X相同,该模板类X具有用于这种重写的挂钩,您只需重写您关心的方法,然后获得BASe类的方法,无需vtable。 在内存占用较大的类中,单个vtable指针的成本不高,但是COM中的一些atl类非常小,如果永远不会发生运行时多态性的情况,那么值得节省vtable。 顺便问一下,这是 a posting I found 这将讨论CPU时间性能方面。 |
![]() |
9
3
我唯一能看到虚拟函数会成为性能问题的方法就是在一个紧密的循环中调用许多虚拟函数,以及 当且仅当 它们会导致页面错误或发生其他“重”内存操作。 尽管像其他人所说的,在现实生活中,这几乎永远不会成为你的问题。如果您认为是这样,请运行一个分析器,进行一些测试,并在尝试“取消签名”代码以获得性能优势之前验证这是否真的是一个问题。 |
![]() |
10
3
当类方法不是虚拟的时,编译器通常在内联中执行。相反,当使用指向带有虚函数的类的指针时,只有在运行时才知道实际地址。 这一点在测试中得到了很好的说明,时差约为700%(!):
虚拟函数调用的影响很大程度上取决于情况。 如果在函数内部只有很少的调用和大量的工作,则可以忽略不计。 或者,当它是一个多次重复使用的虚拟调用时,同时执行一些简单的操作——它可能非常大。 |
![]() |
11
2
在我的特定项目中,我已经反复讨论了至少20次。虽然那里 可以 在代码重用、清晰性、可维护性和可读性方面取得了巨大的进步,另一方面,性能仍然受到影响。 做 具有虚拟功能。 在现代笔记本电脑/台式机/平板电脑上,性能的冲击会很明显吗?大概不会吧!但是,在某些嵌入式系统的情况下,性能下降可能是导致代码效率低下的原因,特别是在循环中反复调用虚拟函数的情况下。 这里有一篇关于在嵌入式系统环境中C/C++的最佳实践的日期纸: http://www.open-std.org/jtc1/sc22/wg21/docs/ESC_Boston_01_304_paper.pdf 总而言之:由程序员来理解使用某个构造胜过另一个构造的优缺点。除非你是超级性能驱动的,你可能不关心性能命中,并且应该使用C++中所有整洁的OO东西来帮助你的代码尽可能的使用。 |
![]() |
12
2
在我的经验中,最主要的相关问题是内联函数的能力。如果您有性能/优化需求,要求一个函数需要内联,那么您就不能使该函数成为虚拟的,因为它会阻止这种情况发生。否则,您可能不会注意到差异。 |
![]() |
13
1
需要注意的一点是:
可能比这快:
这是因为第一个方法只调用一个函数,而第二个方法可能调用许多不同的函数。这适用于任何语言的任何虚拟函数。 我说“可能”,因为这取决于编译器、缓存等。 |
![]() |
14
0
使用虚拟函数的性能损失永远不会超过您在设计级别所获得的优势。假设对虚拟函数的调用比直接调用静态函数效率低25%。这是因为通过vmt有一个间接级别。但是,与实际执行函数所花费的时间相比,进行调用所花费的时间通常非常小,因此总的性能成本将很低,特别是在当前硬件性能方面。 此外,编译器有时可以优化并看到不需要虚拟调用,并将其编译为静态调用。所以不要担心使用虚拟函数和抽象类。 |
![]() |
15
-1
我一直在质疑自己这一点,尤其是几年前,我还做了这样一个测试,将标准成员方法调用的时间与虚拟方法调用的时间进行了比较,当时我对结果非常愤怒,因为空的虚拟调用比非虚拟调用慢8倍。 今天,我必须决定是否使用一个虚拟函数在我的缓冲区类、一个性能非常关键的应用程序中分配更多的内存,所以我在谷歌上搜索(找到了你),最后再次进行了测试。
我真的很惊讶它——事实上——真的不再重要了。 虽然拥有比非虚拟更快的入口是有道理的,而且它们比虚拟更快,但通常涉及到计算机的总体负载,不管您的缓存是否有必要的数据,而且尽管您可能能够在缓存级别进行优化,我认为这应该由编译器开发人员完成,而不是由应用程序完成。开发者。 |
![]() |
AstralHex · 矩阵乘法代码工作不正常 5 月前 |
![]() |
Fishie · 作为类成员的智能指针是否仍然自动释放?[关闭] 5 月前 |
![]() |
Die4Toast · 递归调用成员箭头运算符-> 5 月前 |
![]() |
Anka Hanım · 关于结构和动态数组地址的问题 6 月前 |