日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++ 性能剖析 (四):Inheritance 对性能的影响

發布時間:2025/3/20 c/c++ 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++ 性能剖析 (四):Inheritance 对性能的影响 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

(這個editor今天有毛病,把我的format全搞亂了,抱歉!)

?

Inheritance 是OOP 的一個重要特征。雖然業界有許多同行不喜歡inheritance,但是正確地使用inheritance是一個應用層面和架構層面的重要設計決定。 大量使用inheritance,尤其在類似std container 中使用,會對程序性能產生何等影響呢?

從我個人的經驗來看,constructor對創建具有深層inheritance鏈的class,有很大的影響。 如果應用容許,最好使用沒有constructor的基類。下面舉個例子:

struct __declspec(novtable) ITest1

{ virtual void AddRef() = 0;

? ? virtual void Release() = 0;

? ? virtual void DoIt(int x) = 0; };

class CTest: public ITest1

{

int ref;

public: inline CTest() { ref = 0; }

inline void AddRef() { ++ref; }

inline void Release() {--ref; }

inline void DoIt(int x) {ref *= x; }

inline void AddRef2() { ++ref; }

inline void Release2() {--ref; }

inline void DoIt2(int x) {ref *= x; }

static void TestPerf(int loop); };

這是個dummy程序,然而在COM中確是再常見不過。如果我們要大量創建并使用CTest,有經驗的程序員應該看出,ITest1 完全不需要constructor。 根據C++ 說明書,ITest1因為有虛擬函數,屬于“非簡單構造類”,編譯必須產生一個constructor,其唯一的目的是設置ITest1的vtbl (虛擬函數表)。

然而interface的唯一作用是被繼承,所以其vtbl一定是被其繼承類設置。編譯在這種情況下沒必要生成constructor。 微軟在設計ATL時認識到這一點,推出自己的方案來躲避C++官方SPEC的缺陷:VC++提供了novtableclass modifier,告訴編譯:我不需要你的constructor. 然而我在VS 2010中的測試結果卻令人失望:

ITest1的constructor 仍然被生成了,只是它沒有將vtbl賦值而已,這對增進基類構造的性能實為杯水車薪之舉。 下面我們看看這個“毫無用處的constructor”對性能的影響。 我們權且拿出另一個不需要虛擬函數的ITestPOD (POD的意思是“數據而已”)來做比較:

struct ITest1POD

{ inline void AddRef() { }

inline void Release() { }

inline void DoIt(int x) { } };

ITestPOD當然不能完全作interface用(interface必須用虛擬函數),僅僅為了測試。然后,我們設計一個繼承類,和上面的CTest功能完全一樣:

class CTestPOD: public ITest1POD

{

int ref;

public: inline CTestPOD() { ref = 0; }

inline void AddRef() { ++ref; }

inline void Release() {--ref; }

inline void DoIt(int x) {ref *= x; }

};

我們的目的是用這個CTestPOD來和CTest作一番蘋果與蘋果的比較:

void CTest::TestPerf(int loop)

{

clock_t begin = clock();

for(int i = 0; i < loop; ++i) //loop1

{

CTestPOD testPOD; // line1

testPOD.AddRef();

testPOD.DoIt(0);

testPOD.Release();

}

clock_t end = clock();

printf("POD time: %f \n",double(end - begin) / CLOCKS_PER_SEC);

begin = clock();

for(int i = 0; i < loop; ++i) //loop2

{

CTest test; // line2

test.AddRef2();

test.DoIt2(0);

test.Release2();

}

end = clock();

printf("Interface time: %f \n",double(end - begin) / CLOCKS_PER_SEC);

}

上面的loop1loop2的唯一區別在line1和line2,為了避免用虛擬函數,我特意給CTest準備了AddRef2,DoIt2,Release2,三個同樣的但卻是非虛擬的函數,為的是遵循性能測試的一大原理:compare apple to apple。

我將loop設為10萬,測試結果顯示,loop2比loop1的速度低了20% 左右。從生成的代碼來看,唯一的區別是CTest的constructor調用了編譯自動生成的ITest1 的constructor。這個constructor沒有任何作用,卻白占了許多CPU周期。一個好的編譯,應該是可以把這個constructor裁剪掉的,這個靠我們自己去搜索了。

總結

在應用inheritance時,除去基類里無用的constructor,對大量構造的object的性能來說,會有明顯的影響。不幸的是,微軟的__declspec(novtable) class modifier對解決這個問題沒有提供任何幫助。在設計海量存儲的object的應用中,我們應該盡量用POD來做其基類,避免上面CTest類那樣明顯的性能漏洞。

2014-9-3 西雅圖

轉載于:https://www.cnblogs.com/ly8838/p/3955205.html

總結

以上是生活随笔為你收集整理的C++ 性能剖析 (四):Inheritance 对性能的影响的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。