複製鏈接
請複製以下鏈接發送給好友

gprof

鎖定
gprof,打印出程序運行中各個函數消耗的時間,可以幫助程序員找出眾多函數中耗時最多的函數。
中文名
gprof
外文名
gprof
優    點
GNU工具,人手一個
類    別
工具

gprof簡介

產生程序運行時候的函數調用關係,包括調用次數,可以幫助程序員分析程序的運行流程。
有了函數的調用關係,這會讓開發人員大大提高工作效率,不用費心地去一點點找出程序的運行流程,這對小程序來説可能效果不是很明顯,但對於有幾萬,幾十萬代碼量的工程來説,效率是毋庸置疑的!而且這個功能對於維護舊代碼或者是分析Open Source來説那是相當誘人的,有了調用圖,對程序的運行框架也就有了一個大體瞭解,知道了程序的"骨架",分析它也就不會再那麼茫然,尤其是對自己不熟悉的代碼和Open Source。費話不多説了,讓我們開始我們的分析之旅吧!

gprof優缺點

Gprof具有以下優缺點:
(1) 優點:
(a) GNU工具,人手一個;
(b) 混合方法採集信息。
(2) 缺點:
(a) 需要編譯選項支持:
i. 使用gcc/cc編譯和鏈接時需要加入-pg選項
ii. 使用ld鏈接時需要用/lib/gcrt0.o代替crt0.o作為第一個input文件
iii. 如果要調試libc庫需要使用-lc_p代替-lc參數
(b) 調試多線程程序只能統計主線程的信息(所以不能用於kingbase)。

gprof原理

通過在編譯和鏈接你的程序的時候(使用 -pg 編譯和鏈接選項),gcc 在你應用程序的每個函數中都加入了一個名為mcount ( or "_mcount" , or "__mcount" , 依賴於編譯器或操作系統)的函數,也就是説你的應用程序裏的每一個函數都會調用mcount, 而mcount 會在內存中保存一張函數調用圖,並通過函數調用堆棧的形式查找子函數和父函數的地址。這張調用圖也保存了所有與函數相關的調用時間,調用次數等等的所有信息。

gprof命令

-b 不再輸出統計圖表中每個字段的詳細描述。
-q 只輸出函數的調用圖(Call graph的那部分信息)。
-p 只輸出函數的時間消耗列表。
-e Name 不再輸出函數Name 及其子函數的調用圖(除非它們有未被限制的其它父函數)。可以給定多個 -e 標誌。一個 -e 標誌只能指定一個函數。
-E Name 不再輸出函數Name 及其子函數的調用圖,此標誌類似於 -e 標誌,但它在總時間和百分比時間的計算中排除了由函數Name 及其子函數所用的時間。
-f Name 輸出函數Name 及其子函數的調用圖。可以指定多個 -f 標誌。一個 -f 標誌只能指定一個函數。
-F Name 輸出函數Name 及其子函數的調用圖,它類似於 -f 標誌,但它在總時間和百分比時間計算中僅使用所打印的例程的時間。可以指定多個 -F 標誌。一個 -F 標誌只能指定一個函數。-F 標誌覆蓋 -E 標誌。
-z 顯示使用次數為零的例程(按照調用計數和累積時間計算)。

gprof示例

Test.c
#include <stdio.h>
int prime(int n)
{
int i;
for (i=2; i<n; i++)
{
if (n%i == 0)
return 0;
return 1;
}
}
void main(void)
{
int i, n;
n = 1000;
for (i=2; i<=n; i++)
{
if (prime(i))
printf("%d\n", i);
}
}
Gcc -pg -o test test.c
./test
gprof -b test gmon.out |less
Flat profile:
Each sample counts as 0.01 seconds.
% cumulative self self total
time seconds seconds calls Ts/call Ts/call name
100.00 0.02 0.02 main
0.00 0.02 0.00 999 0.00 0.00 prime
^L
Call graph
granularity: each sample hit covers 4 byte(s) for 50.00% of 0.02 seconds
index % time self children called name
<spontaneous>
[1] 100.0 0.02 0.00 main [1]
0.00 0.00 999/999 prime [2]
-----------------------------------------------
0.00 0.00 999/999 main [1]
[2] 0.0 0.00 0.00 999 prime [2]
-----------------------------------------------
^L
Index by function name
[1] main [2] prime

gprof注意

(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信息

% 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.
每一次調用花費在函數的時間(毫秒)。
total the average number of milliseconds spent in this
ms/call function and its descendents per call, if this
function is profiled, else blank.
每一次調用,花費在函數及其衍生函數的平均時間(毫秒)。
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.
函數名