在gprof出現之前,unix系統中已經有類似的工具prof,記錄每個函式的執行次數和時間。prof的缺點是沒有記錄函式呼叫關係,例如a函式呼叫了b函式,a執行了10次,用時1毫秒,b執行了20次,用時2毫秒,在prof中返回的資料就是a執行10次1毫秒,b執行20次2毫秒,沒有把b的執行時間加入到a中,導致在實際應用中,各個函式的執行時間都差不多,很難發現瓶頸。另乙個問題是,如果c函式也呼叫了b函式並且b執行了100次,那麼就不知道這100次中a和c分別呼叫了多少次。
gprof對prof的主要改進就是加入對函式動態呼叫關係的分析和記錄,將子函式的執行時間加入到父函式中。例如在以上例子中,gprof返回的結果將是a用時3毫秒b用時2毫秒。概括起來說,gprof在被評測程式的每個函式執行前插入評測程式,記錄以下三類程式執行資料:
1. 函式執行次數。
2. 函式執行時間。在分時作業系統中,用函式開始時間和結束時間的差作為執行時間不準確,因為這段時間內該函式並不獨佔cpu. 為了解決這個問題,prof和gprof都採用了取樣的方法,即每隔一段時間就對程式計數器(pc)進行取樣,根據多少個取樣點落入該函式的pc範圍來估算實際執行時間。
3. 函式呼叫關係。函式呼叫關係包括動態呼叫關係和靜態呼叫關係,前者是執行時決定,後者是由源**決定的。gprof主要使用動態呼叫關係,輔以靜態關係。在取得了動態函式呼叫關係圖之後,在分析函式執行時間時,將子函式的執行時間加入到父函式中。
簡單介紹了其原理後,再說一下gprof的主要缺陷:
1. 函式執行時間是估計值。如前所說,函式執行時間是通過取樣估算的。這個不是什麼大的問題,一般估算值與實際值相差不大,何況任何測量都不可能100%準確。
2. gprof假設乙個函式的每次執行時間是相同的。這個假設在實際中可能並不成立,例如,如果函式b執行100次,總執行時間時間10毫秒,被a呼叫20次,被c呼叫80次,那麼b的10毫秒中有2毫秒加入到a的執行時間,8毫秒加入到c的執行時間中。實際上,很可能b被a呼叫時的每次執行時間和被c呼叫時的每次執行時間相差很大,所以以上分攤並不準確,但gprof無法做出區分。
3. 不適合存在大量遞迴呼叫的程式。如果存在遞迴呼叫時,函式動態呼叫關係圖中將存在有向環,這樣明顯不能將子函式的執行時間加到其父函式中,否則環將導致這個累加過程無限迴圈下去。gprof對此的解決辦法是用強連通分量(strongly-connected components)將這些遞迴呼叫的函式在呼叫關係圖中坍縮成乙個節點來處理,但在顯示最終結果時仍然分別顯示各個函式的執行時間。缺點是,對於這些遞迴呼叫的函式,其執行時間不包括其子函式的執行時間,如prof一樣。所以當程式中存在大量遞迴呼叫時,gprof退化為老的prof工具。
4. 不能處理內聯函式。由於gprof只記載函式呼叫,如果程式設計師用大量內聯函式的話,將不能被gprof發現。
5. 資料表示不直觀。gprof將結果輸出到二維的終端中,因此對於樹狀結構的表示不夠直觀。當然這不是大問題,習慣了就行。
對於2和3,後來出現的程式效能評測工具有改進方案,那就是不僅記錄程式呼叫關係圖,而且記錄程式呼叫棧。這樣做的話增加了工具的執行負荷,因此需要降低取樣頻率來保證工具的效能。
與缺陷共舞
軟體生產人員和使用者的最佳選擇是承認軟體不可能沒有缺陷的現實,在生產和使用中都引入軟體 容錯 的理念和機制,並把有限的時間和精力放在 關鍵 部位上,而不是一味追求最少的缺陷和不分重點地使用 軟體開發力量,這樣才能達到總體最優的結果。為了了解軟體質量的現狀,從1994年開始,乙個名叫 standish...
紅黑樹的原理,雙紅缺陷,雙黑缺陷
引入紅黑樹的目的是為了實現在維護bst平衡的同時,盡量控制拓撲結構調整的次數,即最好做到每次動態操作後只有o 1 次的拓撲調整。紅黑樹的規則 1 樹根必須是黑色 2 外部節點必須為黑色 3 其餘節點 紅節點只能有黑孩子,即不能出現相鄰的父子兩代都為紅色 4 外部節點到根 所有外部節點的黑深度相同。在...
C陷阱與缺陷
c語言對於符號 包含乙個或多個字元 的識別規則 每乙個符號應該包含盡可能多的字元。也就是說,編譯器將程式分解成符號的方法是,從左到右乙個字元乙個字元地讀入,如果該字元可能組成乙個符號,那麼再讀入下乙個字元,判斷已經讀入的兩個字元組成的字串是否可能是乙個符號的組成部分 如果可能,繼續讀入下乙個字元,重...