深入理解計算機系統筆記一
我看的是《深入理解計算機系統》原書第三版,這真的是一本相見恨晚的好書。看了幾天,有些內容已經在實際程式設計中獲益了。我重點關注的是優化程式效能。作為程式設計師,我們無須為了寫出高效程式碼而去了解一些編譯器的內部工作。但是,為了在C程式中作出好的編碼選擇,我們確實需要了解一些機器程式碼以及編譯器將不同的C語句轉化為機器程式碼的方式。比如一個switch語句是否總是比一系列的if-else語句高效得多?while迴圈比for迴圈更有效嗎?指標引用比陣列索引更有效嗎?(從目前我個人的經驗來看,確實要更有效,週六剛測試的程式碼,比較簡單的程式碼,大概快了10ms,目前我心中對這個原因還是有一定的想法,但還不確定,至少指標的++的操作要比通過索引定址的方式直覺上看來要簡單,近水樓臺先得月)。為什麼將迴圈求和的結果放到一個本地變數中,會比將其放到一個通過引用傳遞過來的引數中,執行起來快很多呢
最讓我印象深刻的是關於編譯器對程式的安全優化,也就是說對於程式可能遇到的所有可能的情況,在C語音標準提供的保證之下,優化後得到的程式和未優化後的版本有一樣的行為,限制編譯器只進行安全的優化。為了理解決定一種程式轉換是否安全的難度,讓我們來看看下面的這兩個過程
void twiddle1(long *xp, long *yp)
{
*xp += *yp;
*xp += *yp;
}
void twiddle2(long *xp, long *yp)
{
*xp += 2* *yp;
}
乍一看,這兩個過程似乎有相同的行為。他們都是講儲存在指標yp指示的位置處的值兩次加到指標xp指示的位置處的值。另一方面,函式twiddle2效率更高一些。它只要求3次記憶體引用(讀*xp,讀*yp,寫*xp),而前者需要6次。因此,如果要編譯器編譯過程twiddle1,我們會認為twiddle2執行的計算能產生更有效的程式碼。
不過,考慮xp指標等於yp的情況。此時函式twiddle1會執行,下面的程式碼段,結果xp的值為原來的4倍。
*xp += *xp;
*xp += *xp;
而函式twiddle會執行下面的計算
*xp += 2* *xp;
結果是xp的值等於原來的3倍。通過這一個例子,我是跪服了搞編譯器優化的大神。