天天看點

《程式設計珠玑(續)(修訂版)》—第1章1.2節使用性能監視工具

本節書摘來自異步社群《程式設計珠玑(續)(修訂版)》一書中的第1章,第1.2節使用性能監視工具,作者【美】jon bentley,更多章節内容可以通路雲栖社群“異步社群”公衆号檢視。

1.2 使用性能監視工具

對于小程式來說,性能監視很容易實作,是以性能監視工具是可有可無的;但是對于開發大軟體來說,性能監視工具則是不可或缺的。brian kernighan①曾經使用行計數性能監視工具,研究了一個用于解釋awk語言程式的4000行的c程式。那時這個awk解釋程式已廣泛使用了多年。掃描該程式75頁長的程式清單就會發現,大多數計數都是成百上千的,有些甚至上萬。一段晦澀的初始化代碼,計數接近百萬。kernighan對一個6行的循環做了幾處修改,程式速度就提高了一倍。他自己可能永遠也猜不出程式的問題源頭所在,但是性能監視工具引導他找到了。

kernighan的這一經曆是相當典型的。在1.7節引用的論文中,don knuth②給出了fortran程式許多方面(包括性能監視)的經驗研究。該論文中有一個被經常引用(而且常常是被錯誤地引用)的命題:“一個程式中不到4%的語句通常占用了一半以上的運作時間。”對許多語言和系統的大量研究表明,對于不處理i/o密集型的大多數程式,大部分的運作時間花在了很小一部分代碼上。這種模式是下述經驗的基礎:

knuth在論文中描述了用行計數性能監視工具進行自我分析的結果。性能監視結果表明,一半的運作時間花在了兩個循環上。結果花了不到一小時修改了幾行代碼,就讓這個性能監視工具的速度提高了一倍。

第14章描述的性能監視結果說明,一個1000行的程式把80%的時間花在一個5行的子程式上。把這個子程式改寫成十幾行,就讓程式的速度提高了一倍。

1984年貝爾實驗室的tom szymanski打算給一個大系統提速,結果卻使該系統慢了10%。他删除了修改的部分,然後多打開了一些性能監視選項以查明失敗原因。他發現占用的存儲空間增加到了原來的20倍,行計數顯示存儲空間的配置設定次數遠多于釋放次數。接下來用一條指令就糾正了錯誤,正确的實作讓系統加速了一倍。

性能監視表明,作業系統一半的時間花在一個隻有少數幾條指令的循環上。改寫微代碼中的這個循環帶來一個量級的提速,但是系統的吞吐量不變:性能組已經優化了系統的空閑循環!

這些經曆引出了上一節粗略提到過的一個問題:應當在什麼輸入上監視程式的性能?查找素數的程式隻有一個輸入n,該輸入強烈影響到時間性能監視:對于小的n,輸入/輸出占大頭;對于大的n,計算占大頭。有的程式的性能監視結果對輸入資料非常不敏感。我猜想大多數計算薪水的程式都有相當一緻的性能監視結果,至少從2月到11月如此。但有的程式的性能監視結果會随輸入不同有巨大變化。難道你從沒有察覺到,你的系統被調整得在制造商的基準資料上運作起來風馳電掣,而處理起你的重要任務時卻慢如蝸牛?仔細挑選你的輸入資料吧。

性能監視工具對于性能之外的任務也有用。在找素數的練習中,它指出了程式p4的一個錯誤。行計數在估計測試覆寫面時極有價值,比如,如果出現零,則說明有代碼未測試。dec公司的dick sites這樣描述性能監視的其他用途:“(1) 在兩層微存儲實作中,決定哪些微代碼放到晶片上;(2) 貝爾北方研究院(bell northern research)的一位朋友某個周末在帶有多重異步任務的實時電話交換軟體系統上實作了語句計數。通過檢視異常計數,他發現了現場安裝的代碼中存在6處錯誤,所有錯誤都涉及不同任務之間的互動。其中一處錯誤用正常調試技術無法成功追蹤到,其餘錯誤還沒有被當作問題(也就是說,這些錯誤症狀可能已經發生,但是沒有人能夠将其歸結為具體的軟體錯誤)。”