準備寫乙個系列,駁斥一下這些年我整理/設計的高效能編碼規範裡,哪些是沒有意義的。為什麼會沒有意義呢?有的原因可能是規則本身是有問題的,有的原因可能是編譯器會幫我們優化,有的可能存在侷限性,還有可能有些其他原因。
第乙個規則:
如果迴圈體內存在邏輯判斷,宜將邏輯判斷移到迴圈體的外面。這是部門社招主觀題的乙個考點,也是一本老書《大話處理器》裡關於**優化的章節開頭的例子。形如下述**:
for(i = 0; i < n; i++)
if(a)
else
理論分析下:
1.如果a是常量/巨集,編譯器應能優化掉另乙個分支;
2.如果a是變數,處理器應有分支**功能,特別是現在一些強大的晶元,用於**的空間應該是很大的。也就是說,對於變化較少的變數,依賴晶元的分支**功能,這個規則是沒有意義的。
3.如果a是經常變化的變數,處理器應不會進行**,在這個場景下,這個規則應該是有意義的。
4.再從設計上分析下,方式二有迴圈語句重複,應該是要盡量避免的。
針對1,設計**如下:
低效**low.c:
#include #include int a = 1;
int sum = 0;
#define n 1000000
int main()
end = clock();
printf("%ld", end - start);
}
高效**high.c:
#include #include int a = 1;
int sum = 0;
#define n 1000000
int main()
結果如下:
從這個實驗結果裡能得出的結論如下:
低效寫法在大部分情況下效率確實低;
在這個典型寫法下,10億次與100萬次迴圈,low和high的差距比例變化不大,均在30%左右;
a=0,即分支**失敗時,low變化不大,high效能惡化24%,low high差距縮小為5%。
(o2與o1差不多)o1優化下,差距比例擴大為50%;
用const宣告變數a,o0下二者幾乎一樣。存疑。
o3優化二者幾乎一樣;存疑。
根據3,應有如下編碼建議:
對於疑問5,取gcc -o0 -fverbose-asm -s low.c,檢視彙編發現,相比於非const,const僅僅是把a替換成了1,能把low**效能提公升30%!從彙編上似乎解釋不了,推測應該是流水帶來的收益。應有如下編碼建議:
對於疑問6,檢視彙編發現,low**結構已優化成與high的基本相同,即在迴圈外層進行條件判斷。還是存疑,有沒有可能o3通過分析**,明確按照a=1的分支編譯。進一步,將a改為0,發現彙編**順序沒有發生變化,開銷均變為a=1的2倍。所以應有如下結論:
如果條件a與迴圈下標i有關係,沒法優化,不在本文討論的範圍內。
文章開頭提到的編碼規範在o3下沒有意義,考慮到迴圈語句重複,我認為不應再堅持這個編碼規範;
執行概率高的分支應放在概率低的分支前面;
對於版本確定無疑的開關,應使用const或者巨集,不應使用普通變數。
android高效能編碼
學習郭霖大神部落格 一 避免建立不必要物件 拼接字串使用stringbuilder或者stringbuffer要比 連線符效能高,因為加號連線符會建立多與物件,拼接的字串越長,加號連線符的效能越低。2 盡量使用基本資料型別代替封裝資料型別,int比integer更加高效。二 靜態優於抽象 如果不需要...
php 編碼規範哪些 php編碼規範
1.php 必須以完整的形式來定界 即不要使用php 短標籤 且保證在關閉標籤後不要有任何空格。2.當乙個字串是純文字組成的時候 即不含有變數 則必須總是以單引號 作為定界符。例如 a example string 3.變數替換中的變數只允許用 變數名 的形式。例如 greeting hello n...
php 編碼規範哪些 PHP編碼規範
很多初學者對編碼規範不以為然,認為對程式開發沒有什麼幫助,甚至因為要遵循規範而影響了學習和開發的進度。或者因為經過一段時間的使用,已經形成了自己的一套風格,所以不願意去改變。這種想法是很危險的。如今的 web 開發,不再是乙個人就可以全部完成的,尤其是一些大型的專案,往往需要十幾人,甚至幾十人來共同...