程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 利器gprof

利器gprof

編輯:關於C語言

    gprof是一個GNU profiler工具,可以采集程序中每個函數的調用次數、每個函數消耗的CPU時間、以及顯示調用關系圖包括每個函數調用花費了多少時間。要查看gprof的官方詳細信息請點擊這裡,也可以參看這裡。

一、原理

   在編譯和鏈接程序的時候,使用-pg選項,這樣gcc/g++就會在應用程序的每個函數中都加入一個名為mcount/_mcount/__mcount的函數,即用-pg編譯的應用程序裡的每個函數都會調用mcount函數,而mcount函數會在內存中保存一張函數調用圖,並通過函數調用堆棧的形式查找子函數和父函數的地址,這張調用圖也保存了所有與函數相關的調用時間、調用次數等所有信息。

二、用法

   運行用-pg編譯和鏈接後生成的應用程序,在程序退出時會在當前路徑生成一個gmon.out文件,這個文件會記錄下采集的監控數據,可以通過命令行方式的gprof或圖形化方式的Kprof來解析監控數據以分析應用程序的性能。

   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)如果要查看庫函數的profiling,需要在編譯時再加入-lc_p編譯參數,這樣程序會鏈接libc_p庫,從而產生庫函數的profiling信息。

 2)gprof只能在應用程序正常結束退出後才能生產gmon.out文件,這是因為gprof通過在atexit()裡注冊了一個函數來產生結果信息,任何非正常退出都不會執行atexit(),也就不會產生gmon.out文件。通常為了達到這個效果會為應用程序注冊一個信號處理函數以優雅解決此問題,比如:

static void sighandler(int sig_no)
 {
       exit(0);
 }
int main(int argc, char **argv)
{
      signal(SIGUSR1, sighandler);
      ...
}

   當使用kill -USER1 pid後,應用程序會退出並生成gmon.out文件。

三、實例

   下面以簡單實例來說明如何使用gprof,具體代碼如下:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
 static void sighandler( int sig_no )  
{ 
      printf("hello exit\n");
      exit(0);  
 }
void a()
{
     printf("\t\t+---call a() function\n");
}
void c()
{
      printf("\t\t+---call c() function\n");
}
int b()
{
     printf("\t+--- call b() function\n");
     a();
     c();
     return 0;
}
int main()
{
        signal(SIGUSR1, sighandler);
        printf(" main() function()\n");
        b();
       while(true)
      {
            sleep(5);
      }
      return 0;
}

1)使用-pg選項編譯和鏈接應用程序。

   gcc -pg -o test test.c

2)執行應用程序,使之運行完成後生成供gprof分析的數據文件默認是gmon.out)。

  由於本程序是一個永不退出的後台程序,所以就不僅僅是./test了,而需要如下來退出:

  #kill -USR1 pid

  這樣在應用程序所在目錄就會產生gmon.out文件。

3)使用gprof分析應用程序生成的數據文件。

   gprof test gmon.out

   使用上面命令就能分析test的性能了,找出耗時最多的函數或者運算不是夢。

  通常profiling結果都比較多,這樣可以使用管道或者重定向將結果分頁顯示或者輸出到文件中,再具體分析,比如:

gprof test gmon.out | less

gprof test gmon.out > profiling.txt

gprof分析結果會產生如下一些信息:

%time:函數使用時間占所有時間的百分比

cumulative seconds:函數和上列函數累計執行的時間

self seconds:函數本身所執行的時間

calls:函數被調用的次數

self ms/call:每一次調用花費在函數的時間單位微秒)

total ms/call:每一次調用花費在函數及其衍生函數的平均時間單位微秒)

name:函數名

簡單地用-b參數分析下性能,其結果輸出如下:

   從上面的輸出能看出main調用了b,而b又分別調用了a和c,由於函數很簡單,所以每個函數的時間消耗都是0秒。

四、附注

    一般來說,gprof用於查找用戶態層次性能瓶頸,如果你需要查找內核態的性能瓶頸,請使用另一個款開源的profiling工具——oprofile,其使用硬件調試寄存器來統計信息,可以對內核進行profiling,采集cache缺失率、memory訪存信息、分支預測錯誤率等,具體可以參考oprofile官網,也可以參考這裡。

轉載自:http://blog.chinaunix.net/uid-22312037-id-3845961.html

本文出自 “驿落黃昏” 博客,轉載請與作者聯系!

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved