性能問題也不是僅僅用“技術(shù)”可以解決的,它往往是架構(gòu),測試,假設(shè)等綜合難題。不過,對于一個工程師來說,必須從小做起,把一些“明顯”的小問題解決。否則的話積小成多,千里堤壩,潰于蟻穴。
C++ 的性能為什么總是排在C之后 (見http://benchmarksgame.alioth.debian.org/u32/performance.php?test=binarytrees 等網(wǎng)站的最新測試結(jié)果)?我認為這是3個方面的原因:
1)用于測試的C++ 編譯器沒有使用最新的優(yōu)化技術(shù)
2)C++ 附加的價值沒有考慮到測試之中
3)C++ 應(yīng)用層面的“微妙性”(可參考我的關(guān)于C++的其他博客)使得一般程序員往往望而卻步,選擇“教科書用例”,使得一些副作用沒有在應(yīng)用層面被剔出。
記得10多年前,我在微軟做開發(fā)時,曾向C++最早編譯器的作者李伯曼(Stan Lippman)(時任微軟VC++架構(gòu)師)咨詢過一系列我們小組的C++性能難題,在他的幫助下,我們在關(guān)鍵地方用了諸如inline,RVO等技術(shù),完全解決了性能問題,還找出了VC++ 的幾個不小的錯誤。我認識到,C++的性能問題多數(shù)在于我們對C++認識的淺薄,多數(shù)都是不難解決的。
下面用一例子,來做一下對比,看看一些微妙的細節(jié)是如何影響程序性能的。
struct intPair
{
int ip1;
int ip2;
intPair(int i1, int i2) : ip1(i1), ip2(i2) {}
intPair(int i1) : ip1(i1), ip2(i1) {}
};
// Calc sum (usinh value semantic)
Int Sum1(intPair p)
{
return p.ip1 + p.ip2;
}
// Calc sum (usinh ref semantic)
int Sum2(intPair &p)
{
return p.ip1 + p.ip2;
}
// Calc sum (usinh const ref semantic)
Int Sum3(const intPair& p)
{
return p.ip1 + p.ip2;
}
上面這個簡單的struct,有三個Sum函數(shù),作的事情完全一樣,但是性能是否一樣呢?我們用下面的程序來測試:
double Sum(int t, int loop)
{
using namespace std;
if (t == 1)
{
clock_t begin = clock();
int x =0;
for(int i = 0; i < loop; ++i)
{
x += Sum1(intPair(1,2));
}
clock_t end = clock();
return double(end - begin) / CLOCKS_PER_SEC;
}
else if (t == 2)
{
clock_t begin = clock();
int x =0;
intPair p(1,2);
for(int i = 0; i < loop; ++i)
{
x += Sum1(p);
}
clock_t end = clock();
return double(end - begin) / CLOCKS_PER_SEC;
}
else if (t == 3)
{
clock_t begin = clock();
int x =0;
intPair p(1,2);
for(int i = 0; i < loop; ++i)
{
x += Sum2(p);
}
clock_t end = clock();
return double(end - begin) / CLOCKS_PER_SEC;
}
else if (t == 4)
{
clock_t begin = clock();
int x =0;
intPair p(1,2);
for(int i = 0; i < loop; ++i)
{
x += Sum3(p);
}
clock_t end = clock();
return double(end - begin) / CLOCKS_PER_SEC;
}
else if (t == 5)
{
clock_t begin = clock();
int x =0;
for(int i = 0; i < loop; ++i)
{
x += Sum3(10);
}
clock_t end = clock();
return double(end - begin) / CLOCKS_PER_SEC;
}
return 0;
}
我們用了5個案列,對Sum1和Sum3 風別用了兩種調(diào)用方式,對Sum2用了一種調(diào)用方式。我們測試了10萬次調(diào)用:
double sec = Sum(1, 100000);
新聞熱點
疑難解答