国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

C++ 性能剖析 (四):Inheritance 對性能的影響

2019-11-15 01:47:09
字體:
來源:轉載
供稿:網友
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();

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 西雅圖


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 乌鲁木齐市| 绥德县| 房产| 安仁县| 全州县| 苗栗市| 信宜市| 巴塘县| 宝鸡市| 晴隆县| 桑日县| 沭阳县| 和龙市| 唐海县| 徐汇区| 德安县| 育儿| 斗六市| 巴青县| 临沂市| 乃东县| 大邑县| 连州市| 云阳县| 游戏| 乡城县| 金门县| 五家渠市| 商河县| 韶关市| 论坛| 驻马店市| 六枝特区| 琼中| 咸丰县| 上犹县| 屏边| 诏安县| 昌乐县| 朝阳区| 方城县|