Linux C++程式進行效能分析工具gprof使用入門

來源:互聯網
上載者:User

標籤:

 

效能分析工具

 

軟體的效能是軟體品質的重要考察點,不論是線上服務程式還是離線程式,甚至是終端應用,效能都是使用者體驗的關鍵。這裡說的效能重大的範疇來講包括了效能和穩定性兩個方面,我們在做軟體測試的時候也是要重點測試版本的效能表現和穩定性的。對於軟體測試過程中發現的效能問題,如何定位有很多的方法。基本的方法可能是開發人員對代碼進行review,或者是使用一些工具對代碼進行效能分析。常見的效能分析tuning工具有哪些呢?下面兩篇文章做了詳細的總結:

 

 

 

  • https://computing.llnl.gov/tutorials/performance_tools/#Considerations
  • http://en.wikipedia.org/wiki/List_of_performance_analysis_tools

 

在我工作中主要是關於Linux C++程式碼的效能分析,gprof是可用於Linux C++代碼效能profiling的工具之一,本文主要講講我對gprof的學習和使用過程。

 

 

 

Gprof的基本原理

 

gprof能夠讓你知道你的代碼哪些地方是比較耗時的,哪些函數是被調用次數很多的,並且能夠讓你一目瞭然的看到函數與函數之間的調用關係。gprof是gcc/g++編譯器支援的一種效能診斷工具。只要在編譯時間加上-pg選項,編譯器就會在編譯器時在每個函數的開頭加一個mcount函數調用,在每一個函數調用之前都會先調用這個mcount函數,在mcount中會儲存函數的呼叫歷程圖和函數的調用時間和被調次數等資訊。最終在程式退出時儲存在gmon.out檔案中,需要注意的是程式必須是正常退出或者通過exit調用退出,因為只要在exit()被調用時才會觸發程式寫gmon.out檔案。

 

那麼,gprof的使用方法主要以下三步:

 

 

 

  • 會用-pg參數編譯器
  • 運行程式,並正常退出
  • 查看gmon.out檔案

 

 

 

Gprof使用執行個體

 

  1. #include<iostream>  
  2. using namespace std;  
  3.   
  4. int add(int a, int b)  
  5. {  
  6.         return a+b;  
  7. }  
  8.   
  9. int sub(int a, int b)  
  10. {  
  11.         return a-b;  
  12. }  
  13.   
  14. int call ()  
  15. {  
  16.         std::cout << add(1,2) << std::endl;  
  17.         std::cout << sub(2,4) << std::endl;  
  18. }  
  19.   
  20. int main()  
  21. {  
  22.         int a=1, b=2;  
  23.         cout << add(a,b) << endl;  
  24.         for (int i=0; i<10000; i++)  
  25.                 call();  
  26.         return 0;  
  27. }  

使用g++編譯並加上-pg參數:

 

  1. g++ -o hello hello_grof.cpp -pg -g  

得到可執行檔,我們可以使用readelf查看一下它的符號表裡和沒有-pg時編譯的有啥不同:readelf -r ./hello和readelf -r ./hello_normal得出的結果對比。

左邊為有-pg參數編譯的結果。可以看出多了三個函數符號_mcount, __monstartup, _mcleanup都是和gprof相關的調用。

 

 

 

使用gdb調試hello程式,在mcount函數中打斷點也可以看到其調用關係,在add函數執行前先調用mcount函數:

 

 

 

 

 

 

 

接下來運行程式./hello,會在目前的目錄下產生gmon.out檔案。使用gprof查看檔案資訊:

 

  1. gprof -b ./hello gmon.out  
得到如下輸出:
  1. Flat profile:  
  2.   
  3. Each sample counts as 0.01 seconds.  
  4.  no time accumulated  
  5.   
  6.   %   cumulative   self              self     total             
  7.  time   seconds   seconds    calls  Ts/call  Ts/call  name      
  8.   0.00      0.00     0.00    10001     0.00     0.00  add(int, int)  
  9.   0.00      0.00     0.00    10000     0.00     0.00  sub(int, int)  
  10.   0.00      0.00     0.00    10000     0.00     0.00  call()  
  11.   0.00      0.00     0.00        1     0.00     0.00  global constructors keyed to _Z3addii  
  12.   0.00      0.00     0.00        1     0.00     0.00  __static_initialization_and_destruction_0(int, int)  
  13.   
  14.             Call graph  
  15.   
  16.   
  17. granularity: each sample hit covers 2 byte(s) no time propagated  
  18.   
  19. index % time    self  children    called     name  
  20.                 0.00    0.00       1/10001       main [7]  
  21.                 0.00    0.00   10000/10001       call() [10]  
  22. [8]      0.0    0.00    0.00   10001         add(int, int) [8]  
  23. -----------------------------------------------  
  24.                 0.00    0.00   10000/10000       call() [10]  
  25. [9]      0.0    0.00    0.00   10000         sub(int, int) [9]  
  26. -----------------------------------------------  
  27.                 0.00    0.00   10000/10000       main [7]  
  28. [10]     0.0    0.00    0.00   10000         call() [10]  
  29.                 0.00    0.00   10000/10001       add(int, int) [8]  
  30.                 0.00    0.00   10000/10000       sub(int, int) [9]  
  31. -----------------------------------------------  
  32.                 0.00    0.00       1/1           __do_global_ctors_aux [13]  
  33. [11]     0.0    0.00    0.00       1         global constructors keyed to _Z3addii [11]  
  34.                 0.00    0.00       1/1           __static_initialization_and_destruction_0(int, int) [12]  
  35. -----------------------------------------------  
  36.                 0.00    0.00       1/1           global constructors keyed to _Z3addii [11]  
  37. [12]     0.0    0.00    0.00       1         __static_initialization_and_destruction_0(int, int) [12]  
  38. -----------------------------------------------  
  39.   
  40. Index by function name  
  41.   
  42.   [11] global constructors keyed to _Z3addii (hello_grof.cpp) [9] sub(int, int) [10] call()  
  43.    [8] add(int, int)          [12] __static_initialization_and_destruction_0(int, int) (hello_grof.cpp)  

可以使用運行命令:

 

  1. gprof -b ./hello  gmon.out | gprof2doc.py > ~WWW/hello.dot  

產生dot格式的呼叫歷程圖檔案,可以使用windows版的GVEdit for Graphviz軟體查看呼叫歷程圖:

 

 

 

 

附上一張比較複雜的程式呼叫歷程圖:

 

 

對於調用的關係和調用熱點一目瞭然。

 

 

 

Gprof輸出解讀

 

這部分內容可將gprof -b ./hello中的-b參數去掉,可以顯示欄位的詳細含義描述:

 

 

 

  1. 14  %         the percentage of the total running time of the  
  2. 15 time       program used by this function.  
  3. 16  
  4. 17 cumulative a running sum of the number of seconds accounted  
  5. 18  seconds   for by this function and those listed above it.  
  6. 19  
  7. 20  self      the number of seconds accounted for by this  
  8. 21 seconds    function alone.  This is the major sort for this  
  9. 22            listing.  
  10. 23  
  11. 24 calls      the number of times this function was invoked, if  
  12. 25            this function is profiled, else blank.  
  13. 26  
  14. 27  self      the average number of milliseconds spent in this  
  15. 28 ms/call    function per call, if this function is profiled,  
  16. 29        else blank.  
  17. 30  
  18. 31  total     the average number of milliseconds spent in this  
  19. 32 ms/call    function and its descendents per call, if this  
  20. 33        function is profiled, else blank.  
  21. 34  
  22. 35 name       the name of the function.  This is the minor sort  
  23. 36            for this listing. The index shows the location of  
  24. 37        the function in the gprof listing. If the index is  
  25. 38        in parenthesis it shows where it would appear in  
  26. 39        the gprof listing if it were to be printed.  


總結

 

 

 

gprof是常見的效能分析工具,在此羅列一下它的一些不足,也是從網上看的:

 

 

 

  • 1、對多線程支援不好,不準確
  • 2、必須退出exit()才行
  • 3、它只能分析應用程式在運行過程中所消耗掉的使用者時間,無法得到程式核心空間的已耗用時間。對核心態的調用分析無能為力。如果程式系統調用比率比較大,就不適合。

 

Linux C++程式進行效能分析工具gprof使用入門

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.