天天看點

用好binutils之gporf

gporf被稱為GNU簡檔器,是binutils中的一個程式。這個程式可以幫我們找出程式運作時需要處理時間最長的函數。通過它我們可以有效的改善我們程式的效率。

為了有效的使用我們的gprof工具,必須確定參數-pg編譯希望監視的函數 ,用這個參數編譯源代碼,會為程式的每個函數插入對mcount自子例程的調用,當運用程式運作時,mcount子例程建立一個調用圖表簡檔檔案,即gmon.out,它包含了程式中每個函數的計時資訊。

程式測試完之後,就可以使用gprof程式來檢視調用圖表簡檔檔案,gprof的能夠輸出以下幾項内容:

    一般簡檔報告(flat profile),顯示每個函數在你的程式中花費的時間和被調用的次數。

    調用圖表(call graph),顯示對每個函數的,調用者和被調用者以及次數。每個函數的子路徑執行時間的估計。

    源代碼注釋清單(annotate source listing),是源程式的一份copy,裡面标明了每行執行時間。

下面我們舉個例子,這個程式的名字是test.c

#include <stdio.h>

void fun1()

{

    int i,j;

    for (i=0;i<10000;i++)

        j=i;

}

void fun2()

{

    int i,j;

    fun1();

    for (i=0;i<40000;i++)

        j=i;

}

int main()

{

    int i;

    for(i=0;i<100;i++)

        fun1();

    for(i=0;i<1000;i++)

        fun2();

    return(0);

}

主程式有兩個循環,一個調用fun1()100次,一個調用fun2()1000次,而在每個函數fun2()又都調用函數fun1(),是以fun1()總共調用了1100次,但還是fun2()占了更多的時間。

下一步使用-pg參數編譯程式,以便能夠使用gprof。編譯之後運作程式。

$gcc -o test test.c -pg

$./test

程式運作結束後會産生gmon.out調用圖表檔案,檢視一下生成的檔案

$ls -al gmon.out

-rw-rw-r-- 1 secularbird secularbird 464 2007-10-16 22:38 gmon.out

接下來運作gprof,由于産生的輸出是到标準輸出的,是以我們進行一次重定向

$gprof test > gprof.txt

注:gprof的預設參數是 -p -g對于不同的系統可能有些不同。

下面是我gprof.txt檔案中的一部分,各人的結果可能有點不同

Flat profile:

Each sample counts as 0.01 seconds.

  %   cumulative   self              self     total           

 time   seconds   seconds    calls  us/call  us/call  name   

 85.31      0.28     0.28     1000   281.51   327.21  fun2

 15.23      0.33     0.05     1100    45.70    45.70  fun1

由此可見和我們之前分析的一樣,fun1調用了1100次,fun2被調用了1000次,fun2占用了85.31%即大部分的時間。

             Call graph (explanation follows)

granularity: each sample hit covers 2 byte(s) for 3.01% of 0.33 seconds

index % time    self  children    called     namea

                                                 <spontaneous>

[1]    100.0    0.00    0.33                 main [1]

                0.28    0.05    1000/1000        fun2 [2]

                0.00    0.00     100/1100        fun1 [3]

-----------------------------------------------

                0.28    0.05    1000/1000        main [1]

[2]     98.6    0.28    0.05    1000         fun2 [2]

                0.05    0.00    1000/1100        fun1 [3]

-----------------------------------------------

                0.00    0.00     100/1100        main [1]

                0.05    0.00    1000/1100        fun2 [2]

[3]     15.2    0.05    0.00    1100         fun1 [3]

在call gprah中可以看出index[1]在main函數中fun1總共被調用了100次,fun2總共被調用了1000次,

index[2]在整個的程式中,fun2總共被調用了1000次,而fun2總共調用了fun1 1000次。

index[3]在整個的程式中,main調用100次的fun1,fun2調用了1000次的fun1,fun1總共被調用了1100次

以上内容僅供參考,實際情況可以設定gprof參數得到個人所需的内容。

參考資料

    《Professional Assemble language》Richard Blum著

    man gprof