Linux C++程式進行效能分析工具gprof使用入門
效能分析工具
軟體的效能是軟體質量的重要考察點,不論是線上服務程式還是離執行緒序,甚至是終端應用,效能都是使用者體驗的關鍵。這裡說的效能重大的範疇來講包括了效能和穩定性兩個方面,我們在做軟體測試的時候也是要重點測試版本的效能表現和穩定性的。對於軟體測試過程中發現的效能問題,如何定位有很多的方法。基本的方法可能是開發者對程式碼進行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使用例項
- #include<iostream>
- using namespace std;
- int add(int a, int b)
- {
- return a+b;
- }
- int sub(int a, int b)
- {
- return a-b;
- }
- int call ()
- {
- std::cout << add(1,2) << std::endl;
- std::cout << sub(2,4) << std::endl;
- }
- int main()
- {
- int a=1, b=2;
- cout << add(a,b) << endl;
- for (int i=0; i<10000; i++)
- call();
- return 0;
- }
使用g++編譯並加上-pg引數:
- g++ -o hello hello_grof.cpp -pg -g
得到可執行檔案,我們可以使用readelf檢視一下它的符號表裡和沒有-pg時編譯的有啥不同:readelf -r ./hello和readelf -r ./hello_normal得出的結果對比。
使用gdb除錯hello程式,在mcount函式中打斷點也可以看到其呼叫關係,在add函式執行前先呼叫mcount函式:
接下來執行程式./hello,會在當前目錄下生成gmon.out檔案。使用gprof檢視檔案資訊:
- gprof -b ./hello gmon.out
- 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 10001 0.00 0.00 add(int, int)
- 0.00 0.00 0.00 10000 0.00 0.00 sub(int, int)
- 0.00 0.00 0.00 10000 0.00 0.00 call()
- 0.00 0.00 0.00 1 0.00 0.00 global constructors keyed to _Z3addii
- 0.00 0.00 0.00 1 0.00 0.00 __static_initialization_and_destruction_0(int, int)
- Call graph
- granularity: each sample hit covers 2 byte(s) no time propagated
- index % time self children called name
- 0.00 0.00 1/10001 main [7]
- 0.00 0.00 10000/10001 call() [10]
- [8] 0.0 0.00 0.00 10001 add(int, int) [8]
- -----------------------------------------------
- 0.00 0.00 10000/10000 call() [10]
- [9] 0.0 0.00 0.00 10000 sub(int, int) [9]
- -----------------------------------------------
- 0.00 0.00 10000/10000 main [7]
- [10] 0.0 0.00 0.00 10000 call() [10]
- 0.00 0.00 10000/10001 add(int, int) [8]
- 0.00 0.00 10000/10000 sub(int, int) [9]
- -----------------------------------------------
- 0.00 0.00 1/1 __do_global_ctors_aux [13]
- [11] 0.0 0.00 0.00 1 global constructors keyed to _Z3addii [11]
- 0.00 0.00 1/1 __static_initialization_and_destruction_0(int, int) [12]
- -----------------------------------------------
- 0.00 0.00 1/1 global constructors keyed to _Z3addii [11]
- [12] 0.0 0.00 0.00 1 __static_initialization_and_destruction_0(int, int) [12]
- -----------------------------------------------
- Index by function name
- [11] global constructors keyed to _Z3addii (hello_grof.cpp) [9] sub(int, int) [10] call()
- [8] add(int, int) [12] __static_initialization_and_destruction_0(int, int) (hello_grof.cpp)
可以使用執行命令:
- gprof -b ./hello gmon.out | gprof2doc.py > ~WWW/hello.dot
生成dot格式的呼叫關係圖檔案,可以使用windows版的GVEdit for Graphviz軟體檢視呼叫關係圖:
附上一張比較複雜的程式呼叫關係圖:
對於呼叫的關係和呼叫熱點一目瞭然。
Gprof輸出解讀
這部分內容可將gprof -b ./hello中的-b引數去掉,可以顯示欄位的詳細含義描述:
- 14 % the percentage of the total running time of the
- 15 time program used by this function.
- 16
- 17 cumulative a running sum of the number of seconds accounted
- 18 seconds for by this function and those listed above it.
- 19
- 20 self the number of seconds accounted for by this
- 21 seconds function alone. This is the major sort for this
- 22 listing.
- 23
- 24 calls the number of times this function was invoked, if
- 25 this function is profiled, else blank.
- 26
- 27 self the average number of milliseconds spent in this
- 28 ms/call function per call, if this function is profiled,
- 29 else blank.
- 30
- 31 total the average number of milliseconds spent in this
- 32 ms/call function and its descendents per call, if this
- 33 function is profiled, else blank.
- 34
- 35 name the name of the function. This is the minor sort
- 36 for this listing. The index shows the location of
- 37 the function in the gprof listing. If the index is
- 38 in parenthesis it shows where it would appear in
- 39 the gprof listing if it were to be printed.
總結
gprof是常見的效能分析工具,在此羅列一下它的一些不足,也是從網上看的:
- 1、對多執行緒支援不好,不準確
- 2、必須退出exit()才行
- 3、它只能分析應用程式在執行過程中所消耗掉的使用者時間,無法得到程式核心空間的執行時間。對核心態的呼叫分析無能為力。如果程式系統呼叫比率比較大,就不適合。
相關文章
- Linux C++ 開發9 - 手把手教你使用gprof效能分析工具LinuxC++
- Linux效能評測工具之一:gprof篇Linux
- linux高階工具命令(三)使用gprof和oprofile查詢效能瓶頸Linux
- 使用pprof進行效能分析
- 使用 XDebug + Webgrind 進行 PHP 程式效能分析WebPHP
- 使用 Python 進行資料分析:入門指南Python
- c++效能測試工具:google benchmark入門(二)C++Go
- Docker中使用Xhprof 對程式碼進行效能分析Docker
- JMeter效能測試工具使用入門JMeter
- 使用YCSB工具工具進行cassandra效能測試
- ORACLE 使用TRACE進行SQL效能分析OracleSQL
- Linux效能分析工具Linux
- 使用 Sysbench 進行 Linux 效能測試Linux
- 使用VisualVM對JAVA程式進行效能分析及調優LVMJava
- 使用Iperf工具進行網路效能測試
- 使用DBMS_PROFILER進行PL/SQL效能分析SQL
- 使用JDK自帶的VisualVM進行Java程式的效能分析JDKLVMJava
- 利用perf進行效能分析
- Linux程式多執行緒入門Linux執行緒
- Python 效能分析入門指南Python
- gprof的效能優化實踐優化
- Linux 效能分析工具彙總Linux
- linux / aix 效能分析工具nmonLinuxAI
- 使用火焰圖進行Java應用效能分析Java
- 使用xhprof進行線上PHP效能追蹤及分析PHP
- 使用 Spark 進行微服務的實時效能分析Spark微服務
- NLP入門(十)使用LSTM進行文字情感分析
- 使用應用程式跟蹤對效能改變進行量化分析(轉)
- perf效能分析工具使用分享
- 使用Dstat來進行Linux綜合效能診斷Linux
- 《MySQL 進階篇》十四:效能分析工具MySql
- linux 效能分析工具dstat之一Linux
- Linux 效能分析工具彙總合集Linux
- linux效能分析工具之火焰圖Linux
- WPF 使用 Silk.NET 進行 DirectX 渲染入門
- 使用JMeter進行負載測試快速入門JMeter負載
- 如何使用Docker進行Java入門級開發DockerJava
- 使用 Python 進行社交媒體情感分析入門Python