在查阅某个问题的时候,突然看到了关于各个操作的性能损耗,今天就借助这篇文章,聊聊我们印象中性能很差的虚函数~~。
关于虚函数
对于虚函数(virtual function)的实现机制,在此就不再赘述了,本节我们聊聊关于虚函数的性能消耗这块。
下面且看一个例子:
emm,相信很多人看过Stanley B. Lippman的<
那么,上面Base类中,fun()函数的实现,在编译器看来,可能如下:
继续看下面这段代码:
在上述代码中,有两个Base类型的指针,分别指向基类Base和派生类Derived,那么其调用机制又如何呢?
首先,与非virtual函数实现机制一样,对于virtual函数,都会增加一个默认的指向实际对象的this指针。
其次,编译器在包含虚函数的类中添加一个隐含的指针vptr指向类的虚函数表,一般情况下,这个vptr指针在对象的最前面
最后,在运行时,通过查找虚函数表,进而找到正确的应该被调用的函数。
也就是说,对于虚函数的调用,最终,编译器可能会变成:
好了,上述这个过程仅仅是本文的后续内容的一个铺垫,往往,我们说虚函数性能差,是因为虚表的查找过程导致性能较普通函数或者普通成员函数查,嗯,相信很多人和我一样,认为这个差,是很差~~
性能
直到我昨天在查阅某个问题的时候,恰好看了一张各种操作的性能分析图,算是颠覆了之前的某些认知。
好了,图来了~~
从上图可以看出,我们所理解的虚函数性能(准确的说是查虚表)的性能,与L3差不多,整数除法操作的一半性能。
基于上图,可以看下代码中哪些地方可以优化,当然了,可以从底部开始(如果非要从顶部开始的话,也没人拦着~),如果非要总结的话,那就如下几点:
• 一次IO毁所有
• 多线程只是可选,如果单线程能完成且性能不错的前提下,慎用多线程,毕竟其上下文切换开销很大
• 异常处理的性能损耗超过我们想象
• 尽量避免系统/内核调用
最后,以潇洒哥的一句话,结束本文: