一文略懂性能分析工具之 gprof
在軟件開發過程中,性能優化是非常重要的一環。再好的算法,如果資源佔用高,部署平臺用不起來,也是水中月,鏡中花。
程序開發過程中遇到的性能問題,比如 CPU 佔用高、內存泄漏等,需要使用性能分析工具來快速定位問題,定位問題能力也是工程能力的表現。
基於 Linux 系統,性能分析工具很多,涉及 CPU、內存、IO、網絡等。下圖是 Brendan Gregg 非常經典的性能分析工具圖,本系列文章根據實際開發經驗,介紹幾款常用的性能分析工具、基本用法和使用思路,拋磚引玉。
perf、valgrind、gprof 和 gperftools 四款工具是使用較多的性能分析工具,四種工具的簡單對比如下表,本文主要介紹 gprof 工具的使用。
01 基本工具的安裝
爲了工具安裝和分析數據可視化,需要如下幾款工具軟件。
1.autoconf、automake、libtool
GNU Autoconf 構建系統,開源軟件中經常會使用該構建系統管理編譯流程。如果下載的開源軟件包中有 configure.ac 和 Makefile.am 文件,說明該開源軟件可以使用 GNU Autoconf 構建系統編譯。基本指令如下:
autoreconf -i
./configure
make
make install
Linux 系統下安裝命令如下:
sudo apt-get install --assume-yes autoconf automake libtool
2.CMake
CMake 是一個跨平臺的安裝(編譯)工具,可以用簡單的語句來描述所有平臺的安裝 (編譯過程)。
Linux 系統下安裝命令如下:
sudo apt-get install --assume-yes cmake build-essential
3.kcachegrind
圖形化性能分析工具,支持 callgrind 格式的性能分析數據可視化顯示。
Linux 系統下安裝命令如下:
sudo apt-get install --assume-yes kcachegrind
4.graphviz
一個由 AT&T 實驗室啓動的開源工具包,用於繪製 DOT 語言腳本描述的圖形。使用該工具可以將性能分析工具轉換成 DOT 格式,進而轉換成圖形分析結果。
Linux 系統下安裝命令如下:
sudo apt-get install --assume-yes graphviz
5.ghostscript
一個用於 PostScript 語言和 PDF 文件的解釋器。ghostscript 由一個 PostScript 解釋器層和一個圖形庫組成。ghostscript 可以查看及打印 PS、EPS、PDF 文件,使用該工具可以將性能分析結果轉換成 pdf 文件。
Linux 系統下安裝命令如下:
sudo apt-get install --assume-yes ghostscript
02 gprof 介紹
gprof(GNU profiler) 是 GNU binutils 工具集中的自帶工具。如果使用 GCC 編譯器,可以使用它分析程序性能:函數調用時間、調用次數和調用關係,找出程序的瓶頸所在。
官方說明地址如下:
https://sourceware.org/binutils/docs/gprof/index.html
1.gprof 的功能
-
flat profile:分析每個函數的調用次數,每個函數花費的時間;
-
call graph:分析函數的調用關係,每個函數調用花費的時間;
-
annotated source:分析程序中每行代碼的執行次數;
2.gprof 的原理
通過在編譯和鏈接時使用 - pg 選項,gcc 在應用程序的每個函數中都加入了一個名爲 mcount (也可能是”_mcount” 或者”__mcount”, 依賴於編譯器或操作系統) 的函數。這樣應用程序裏的每一個函數都會調用 mcount, 而 mcount 會在內存中保存一張函數調用圖:記錄通過函數調用堆棧找到的子函數和父函數的地址,以及所有與函數相關的調用時間,調用次數等信息。
03 gprof 使用
- 在編譯程序的時候,需要添加 - pg 編譯選項;
典型的 GCC 編譯指令如下:
gcc -pg -o test test.c
如果使用 CMake,指令如下:
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pg")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg")
-
正常執行編譯後的可執行程序,如果生成 gmon.out 文件,說明 gprof 正常運行;
該步驟運行程序的時間會稍慢於正常編譯的可執行程序的運行時間。程序運行結束後,會在程序所在路徑下生成一個缺省文件名爲 gmon.out 的文件。這個文件就是記錄程序運行的性能、調用關係、調用次數等信息的數據文件。
-
使用 gprof 命令來分析記錄程序運行信息的 gmon.out 文件;
基本命令形式如下:
gprof options [executable-file [profile-data-files…]] [> outfile]
options 可選的參數如下:
-
-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 標誌;
可以使用下面的命令,生成 TXT 數據分析報告,[] 中需要替換爲實際使用的內容。
gprof [bin] gmon.out > [name].txt
04 gprof 數據分析
1.TXT 數據分析報告
在生成的 TXT 分析數據中,總共有三張表。
第一張表:Flat Profile 每個函數的調用次數,每個函數花費的時間
第二張表:Call Graph 函數的調用關係,每個函數調用花費的時間
第三張表:Index by function name 函數與其在報告中序號的對應表
2. 數據可視化分析
如果只是單純的看 TXT 分析結果,對於一些大型程序還是不直觀,所以可以使用 gprof2dot.py 工具將 TXT 轉換成 DOT,然後再轉換成圖片。
gprof2dot.py 工具地址:
https://github.com/jrfonseca/gprof2dot.git
使用如下命令:
gprof2dot.py -n0 -e0 -s -w [name].txt > [name].dot
dot -Tpng [name].dot -o [name].png
其中 gprof2dot.py 命令中 “-n0”、“-e0” 修改顯示節點的閾值,默認是 0.5 和 0.1,這樣可以顯示全部的分析結果;“-s”、“-w”隱藏、摺疊函數參數等,可以優化顯示效果。
下面兩個圖分別是同一分析數據不加 “-n0 -e0 -s -w” 和添加之後的效果。
05 gprof 使用思路
1.gprof 的優勢
-
簡單易用。只需要在編譯和鏈接時增加 - pg 選項。gprof 對於代碼大部分是用戶空間的 CPU 密集型的應用程序用處明顯;
-
GNUBinutils 的組成部分,基本上任何 Linux 裏面都有。可以把生成的 gmon.out 拷貝到 host 上進行分析,省掉了一部分交叉編譯的工作量;
2.gprof 的劣勢:
-
只能監控到編譯和鏈接時有 - pg 選項的函數,工作在內核態的函數和沒有加 - pg 編譯的第三方庫函數無法被監控。因此 gprof 比較適合執行時間大部分在用戶態的應用;
-
不能監控 shared library,即. so 的文件;
-
不支持多線程應用,多線程下只能採集主線程性能數據。原因是在多線程內只有主線程才能響應 gprof 採用的 ITIMER_PROF 信號。下文的地址是解決該問題的一個方案,但是實際測試效果還是不理想。
http://sam.zoy.org/writings/programming/gprof.html
- 只能在程序正常結束退出,或者通過系統調用 exit() 退出之後才能生成報告(gmon.out)。原因是 gprof 通過在 atexit() 裏註冊了一個函數來產生結果信息,任何非正常退出都不會執行 atexit() 的動作,所以不會產生 gmon.out 文件;
3. 使用建議:
如果程序使用 GCC 編譯,並且是屬於 CPU 密集型程序,在實際環境中沒有其它更好的工具提供的時候,可以使用 gprof 分析程序,初步定位問題。如果有更多需求,可以關注後續文章 gperftools、perf、valgrind。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/Bf2JyeIjNdJCUedaQfWWyQ