Linux下程式的Profile工具

來源:互聯網
上載者:User

我們在寫程式,特別是嵌入式程式的時候,通常需要對程式的效能進行分析,以便程式能夠更快更好地運行,達到即時(real-time)的目的。如果程式很大,分析起來就很困難。如果有個工具能夠自動進行程式的效能分析,那就最好了。這裡介紹一種Linux下程式的Profiling工具----GNU profiler。 

gprof的基本用法:

1. 使用 -pg 選項編譯和連結你的應用程式

        在gcc編譯器的時候,加上-pg選項,例如:

    gcc -pg -o test test.c

    這樣就產生了可執行檔test。如果是大項目,就在makefile裡面修改編譯選項,-pg放在那裡都行。

 

2. 執行你的應用程式使之產生供gprof 分析的資料

 

    運行剛才的程式:./test,這樣就產生了一個gmon.out檔案,該檔案就包含了profiling的資料。

 

3. 使用gprof 分析你的應用程式產生的資料

 

    gprof test gmon.out > profile.txt

    使用上面的命令,gprof就可以剖析器test的效能,將profiling的結果放在profile.txt檔案中,開啟就可以看到分析的結果。通過對結果的分析來改進我們的程式,從而達到我們的目的。

GNU gprof是個很不錯的工具,大家寫程式時可以多用用。我現在用gprof來profiling我的程式,把耗時最多的函數或運算找出來,用FPGA晶片實現,從而達到real-time的目的。

 

為gprof編譯器

在編譯或連結來源程式的時候在編譯器的命令列參數中加入“-pg”選項,編譯時間編譯器會自動在目標代碼中插入用於效能測試的代碼片斷,這些代碼在程式在運行時採集並記錄函數的調用關係和調用次數,以及採集並記錄函數自身執行時間和子函數的調用時間,程式運行結束後,會在程式退出的路徑下產生一個gmon.out檔案。這個檔案就是記錄並儲存下來的監控資料。可以通過命令列方式的gprof或圖形化的Kprof來解讀這些資料並對程式的效能進行分析。另外,如果想查看庫函數的profiling,需要在編譯是再加入“-lc_p”編譯參數代替“-lc”編譯參數,這樣程式會連結libc_p.a庫,才可以產生庫函數的profiling資訊。如果想執行一行一行的profiling,還需要加入“-g”編譯參數。

例如如下命令列:

gcc -Wall -g -pg -lc_p example.c -o example

 

 執行gprof

執行如下命令列,即可執行gprof:

gprof OPTIONS EXECUTABLE-FILE gmon.out BB-DATA [YET-MORE-PROFILE-DATA -FILES...] [> OUTFILE]

 

 gprof產生的資訊

 %                        the percentage of the total running time of the

time                     program used by this function.

                           函數使用時間占所有時間的百分比。

cumulative          a running sum of the number of seconds accounted

 seconds             for by this function and those listed above it.

                           函數和上列函數累計執行的時間。

 self                    the number of seconds accounted for by this

seconds             function alone.  This is the major sort for this

                          listing.

                          函數本身所執行的時間。

calls                   the number of times this function was invoked, if

                          this function is profiled, else blank.

                          函數被調用的次數

 self                   the average number of milliseconds spent in this

ms/call               function per call, if this function is profiled,

                         else blank.

                          每一次調用花費在函數的時間microseconds。

 total                  the average number of milliseconds spent in this

ms/call               function and its descendents per call, if this 

                          function is profiled, else blank.

                          每一次調用,花費在函數及其衍生函數的平均時間microseconds。

name                 the name of the function.  This is the minor sort

                          for this listing. The index shows the location of

                          the function in the gprof listing. If the index is

                          in parenthesis it shows where it would appear in

                          the gprof listing if it were to be printed.

                          函數名

 

prof 實現原理:

通過在編譯和連結你的程式的時候(使用 -pg 編譯和連結選項),gcc 在你應用程式的每個函數中都加入了一個名為mcount ( or “_mcount” , or “__mcount” , 依賴於編譯器或作業系統)的函數,也就是說你的應用程式裡的每一個函數都會調用mcount, 而mcount 會在記憶體中儲存一張函數調用圖,並通過函數呼叫堆疊的形式尋找子函數和父函數的地址。這張調用圖也儲存了所有與函數相關的調用時間、調用次數等等的所有資訊。

 

Gprof 簡單使用:

 

 

讓我們簡單的舉個例子來看看Gprof是如何使用的。

1.開啟linux終端。建立一個test.c檔案,並生用-pg 編譯和連結該檔案。

 

test.c 檔案內容如下:

引文:

 

        #include "stdio.h"

       #include "stdlib.h"

 

 

void a(){

    printf("/t/t+---call a() function ");

}

 

 

void c(){

    printf("/t/t+---call c() function ");

}

 

 

int b() {

    printf("/t+--- call b() function ");

    a();

    c();

    return 0;

}

 

 

 

int main(){

    printf(" main() function() ");

    b();

}

 

命令列裡面輸入下面命令,沒加-c選項,gcc 會預設進行編譯並連結產生a.out:

引文:

 

[linux /home/test]$gcc -pg test.c

 

如果沒有編譯錯誤,gcc會在目前的目錄下產生一個a.out檔案,當然你也可以使用 –o 選項給產生的檔案起一個別的名字,像 gcc –pg test.c –o test , 則gcc會產生一個名為test的可執行檔,在命令列下輸入[linux /home/test]$./test ,就可以執行該程式了,記住一定要加上 ./ 否則程式看上去可能是執行,可是什麼輸出都沒有。

 

2.執行你的應用程式使之產生供gprof 分析的資料。 命令列裡面輸入:

引文:

 

[linux /home/test]$a.out

main() function()

    +--- call b() function

        +---call a() function

        +---call c() function

[linux /home/test]$

 

你會在目前的目錄下看到一個gmon.out 檔案, 這個檔案就是供gprof 分析使用的。

 

3.使用gprof 程式分析你的應用程式產生的資料。

命令列裡面輸入:

引文:

 

[linux /home/test]$ gprof -b a.out gmon.out | less

 

由於gprof輸出的資訊比較多,這裡使用了 less 命令,該命令可以讓我們通過上下方向鍵查看gprof產生的輸出,|表示gprof -b a.out gmon.out 的輸出作為 less的輸入。下面是我從gprof輸出中摘抄出的與我們有關的一些詳細資料。

引文:

 

Flat profile:

 

Each sample counts as 0.01 seconds.

 no time accumulated

 

  %   cumulative   self              self     total

 time   seconds   seconds    calls  Ts/call  Ts/call  name

  0.00      0.00     0.00        1     0.00     0.00  a

  0.00      0.00     0.00        1     0.00     0.00  b

  0.00      0.00     0.00        1     0.00     0.00  c

 

 Call graph

 

 

granularity: each sample hit covers 4 byte(s) no time propagated

 

index % time    self  children    called     name

                0.00    0.00       1/1           b [2]

[1]      0.0    0.00    0.00       1         a [1]

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

                0.00    0.00       1/1           main [10]

[2]      0.0    0.00    0.00       1         b [2]

                0.00    0.00       1/1           c [3]

                0.00    0.00       1/1           a [1]

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

                0.00    0.00       1/1           b [2]

[3]      0.0    0.00    0.00       1         c [3]

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

 

Index by function name

 

   [1] a                       [2] b                       [3] c

 

從上面的輸出我們能明顯的看出來,main 調用了 b 函數, 而b 函數分別調用了a 和 c 函數。由於我們的函數只是簡單的輸出了一個字串,故每個函數的消耗時間都是0 秒。

 

使用gprof剖析器

 

gprof介紹

gprof是一個GNU profiler工具。可以顯示程式啟動並執行“flat profile”,包括每個函數的調用次數,每個函數消耗的處理器時間,也可以顯示“調用圖”,包括函數的調用關係,每個函數調用花費了多少時間。還可以顯示“注釋的原始碼”--是程式原始碼的一個複本,標記有程式中每行代碼的執行次數。

 

基本用法:

1.使用-pg選項編譯和連結你的應用程式。

2. 執行你的應用程式,使之運行完成後產生供gprof分析的資料檔案(預設是gmon.out)。

3. 使用gprof程式分析你的應用程式產生的資料,例如:gporf a.out gmon.out。

 

gprof 實現原理:

gprof並不神奇,在編譯和連結程式的時候(使用 -pg 編譯和連結選項),gcc 在你應用程式的每個函數中都加入了一個名為mcount(or“_mcount”, or“__mcount”)的函數,也就是說-pg編譯的應用程式裡的每一個函數都會調用mcount, 而mcount會在記憶體中儲存一張函數調用圖,並通過函數呼叫堆疊的形式尋找子函數和父函數的地址。這張調用圖也儲存了所有與函數相關的調用時間,調用次數等等的所有資訊。

 

常用的gprof命令選項: 

-b            不再輸出統計圖表中每個欄位的詳細描述。 

-p            只輸出函數的調用圖(Call graph的那部分資訊)。

-q            只輸出函數的時間消耗列表。

-e Name       不再輸出函數Name 及其子函數的調用圖(除非它們有未被限制的其它父函數)。可以給定多個 -e 標誌。一個 -e 標誌只能指定一個函數。

-E Name       不再輸出函數Name 及其子函數的調用圖,此標誌類似於 -e 標誌,但它在總時間和百分比時間的計算中排除了由函數Name 及其子函數所用的時間。

-f Name       輸出函數Name 及其子函數的調用圖。可以指定多個 -f 標誌。一個 -f 標誌只能指定一個函數。 

-F Name       輸出函數Name 及其子函數的調用圖,它類似於 -f 標誌,但它在總時間和百分比時間計算中僅使用所列印的常式的時間。可以指定多個 -F 標誌。一個 -F 標誌只能指定一個函數。-F 標誌覆蓋 -E 標誌。 

-z           顯示使用次數為零的常式(按照調用計數和累積時間計算)。

 

使用注意:

1)一般gprof只能查看使用者函數資訊。如果想查看庫函數的資訊,需要在編譯是再加入“-lc_p”編譯參數代替“-lc”編譯參數,這樣程式會連結libc_p.a庫,才可以產生庫函數的profiling資訊。

2) gprof只能在程式正常結束退出之後才能產生程式測評報告,原因是gprof通過在atexit()裡註冊了一個函數來產生結果資訊,任何非正常退出都不會執行atexit()的動作,所以不會產生gmon.out檔案。如果你的程式是一個不會退出的服務程式,那就只有修改代碼來達到目的。如果不想改變程式的運行方式,可以添加一個訊號處理函數解決問題(這樣對代碼修改最少),例如:

static void sighandler( int sig_no )   

{   

      exit(0);   

}   

signal( SIGUSR1, sighandler );

當使用kill -USR1 pid 後,程式退出,產生gmon.out檔案。

 

 使用gprof和oprofile尋找效能瓶頸

 

有些時候,我們特別關注程式的效能,特別是底層軟體,比如驅動程式、OS等。為了更好的最佳化程式效能,我們必須找到效能瓶頸點,“好鋼用在刀刃上”才能取得好的效果,否則可能白做工作。為了找到關鍵路徑,我們可以使用profilng技術,在linux平台上,我們可以使用gprof和oprofile工具。

 

gprof是GNU工具之一,它在編譯的時候在每個函數的出入口加入了profiling的代碼,運行時統計程式在使用者態的執行資訊,可以得到每個函數的調用次數、執行時間、調用關係等資訊,簡單易懂。適合於尋找使用者級程式的效能瓶頸,對於很多時間都在核心態執行的程式,gprof不適合。  

oprofile也是一個開源的profiling工具,它使用硬體調試寄存器來統計資訊,進行 profiling的開銷比較小,而且可以對核心進行profiling。它統計的資訊非常的多,可以得到cache的缺失率,memory的訪存資訊, 分支預測錯誤率等等,這些資訊gprof是得不到的,但是對於函數調用次數,它是不能夠得到的。。 

    簡單來說,gprof簡單,適合於尋找使用者級程式的瓶頸,而oprofile稍顯複雜,但是得到的資訊更多,更適合調試系統軟體。

    我們以編譯運行hello.c為例,來說明如何使用這兩個工具,這裡不解釋具體結果的含義,要想詳細瞭解每個結果代表什麼意思,可以看一下參考資料中官方網站上的doc資訊,裡面會給你詳盡的解釋。

 

gprof Quick Start

 

    gprof是gnu binutils工具之一,預設情況下linux系統當中都帶有這個工具。

 

使用 -pg 選項來編譯hello.c,如果要得到帶注釋的源碼清單,則需要增加 -g 選項。運行: gcc -pg -g -o hello hello.c  

運行應用程式: ./hello  會在目前的目錄下產生gmon.out檔案  

使用gprof來分析gmon.out檔案,需要把它和產生它的應用程式關聯起來:  

gprof hello gmon.out -p 得到每個函數佔用的執行時間  

gprof hello gmon.out -q 得到call graph,包含了每個函數的調用關係,調用次數,執行時間等資訊。  

gprof hello gmon.out -A 得到一個帶注釋的“原始碼清單”,它會注釋源碼,指出每個函數的執行次數。這需要在編譯的時候增加 -g選項。 

oprofile Quick Start

 

    oprofile是sourceforge上面的一個開源項目,在2.6核心上帶有這個工具,好像只有smp系統才有。比較老的系統,需要自己安裝,重新編譯核心。

    oprofile是一套工具,分別完成不同的事情。

 

op_help:  列出所有支援的事件。

opcontrol:設定需要收集的事件。

opreport: 對結果進行統計輸出。

opannaotate:產生帶注釋的源/彙編檔案,源語言級的注釋需要編譯源檔案時的支援。

opstack:    產生調用圖profile,但要求x86/2.6的平台,並且linux2.6安裝了call-graph patch

opgprof:    產生如gprof相似的結果。

oparchive:  將所有的未經處理資料檔案收集打包,可以到另一台機器上進行分析。

op_import:  將採樣的資料庫檔案從另一種abi轉化成本地格式。

 

    運行oprofile需要root許可權,因為它要載入profile模組,啟動oprofiled背景程式等。所以在運行之前,就需要切換到root。

 

opcontrol --init  載入模組,mout /dev/oprofile 建立必需的檔案和目錄  

opcontrol --no-vmlinux 或者 opcontrol --vmlinux=/boot/vmlinux-`uname -r` 決定是否對kernel進行profiling  

opcontrol --reset 清楚當前會話中的資料  

opcontrol --start 開始profiling  

./hello 運行應用程式,oprofile會對它進行profiling  

opcontrol --dump 把收集到的資料寫入檔案  

opcontrol --stop 停止profiling  

opcotrol -h 關閉守護進程oprofiled  

opcontrol --shutdown 停止oprofiled 

opcontrol --deinit 卸載模組 

常用的是3→7這幾個過程,得到效能資料之後,可以使用opreport, opstack, opgprof, opannotate幾個工具進行分析,我常用的是opreport, opannotate進行分析。

 

opreport使用 http://oprofile.sourceforge.net/doc/opreport.html  

opannotate使用 http://oprofile.sourceforge.net/doc/opannotate.html  

opgprof使用 http://oprofile.sourceforge.net/doc/opgprof.html 

最常用的是opreport,這個可以給出image和symbols的資訊,比如我想得到每個函數的執行時間佔用比例等資訊,用來發現系統效能瓶頸。opannotate可以對源碼進行注釋,指出哪個地方佔用時間比較多。常用命令如下:

 

opreport -l /bin/bash --exclude-dependent --threshold 1 , 用來發現系統瓶頸。

指定查看/bin/bash的profiling資訊,佔用總體執行時間1%以上的函數列表 

opannotate --source --output-dir=annotated /usr/local/oprofile-pp/bin/oprofiled  

opannotate --source --base-dirs=/tmp/build/libfoo/ --search-dirs=/home/user/libfoo/ --output-dir=annotated/ /lib/libfoo.so 

網路資源

 

gprof 使用者手冊 http://sourceware.org/binutils/docs-2.17/gprof/index.html  

oprofile官方網站 http://oprofile.sourceforge.net/  

使用 GNU profiler 來提高代碼運行速度 http://www-128.ibm.com/developerworks/cn/linux/l-gnuprof.html  

使用 OProfile for Linux on POWER 識別效能瓶頸  http://www-128.ibm.com/developerworks/cn/linux/l-pow-oprofile/

 

本篇文章來源於:開發學院 http://edu.codepub.com   原文連結:http://edu.codepub.com/2011/0105/28527.php

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.