一、gprof的安装和说明
在前面谈过了gperftools的安装,今天来看一下gprof的安装。虽然说gperftools安装比较复杂,但是gprof就好说了,因为只要你的机器上装有GCC,那么自然就带了这个软件。如果没有的话,就按照以下的方法安装一下新的gcc即可。不过一般来说,系统都会自带相对最新的gcc,这个不用太担心。
https://blog.csdn.net/fpcc/article/details/99698783?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164531868816780264056766%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=164531868816780264056766&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2blogfirst_rank_ecpm_v1~rank_v31_ecpm-1-99698783.nonecase&utm_term=GCC&spm=1018.2226.3001.4450
同样,为了安装可视化工具可以采用下面的方法:(gprof2dot需要python2.7及以上版本,同样还需要安装Graphviz)
具体的安装过程如下:
1、去清华或者阿里,或者官网下载Anaconda 并安装:https://www.anaconda.com/products/individual
2、安装完成后,关闭当前终端,再次打开,即可使用conda和 python命令,同时pip和pip3工具也安装成功。
3、安装可视化工具pip3 install gprof2dot
4、sudo apt-get install graphviz(默认一般已经安装)
更多可参看gprof相关的文档:
http://sourceware.org/binutils/docs-2.17/gprof/index.html
二、gprof的使用说明
gprof只记录执行时间超过0.01秒即10毫秒的函数调用时间,所以其实对服务器端的应用受到了比较大的限制。gprof在应用时需要注意以下几点:
1、gprof使用时必须增加下列编译选项,否则无法生成gmon.out文件:
“ -pg Generate extra code to write profile information suitable for the
analysis program gprof. You must use this option when compiling
the source files you want data about, and you must also use it when
linking.”
2、gprof原生并不支持多线程应用,只能对主线程数据进行采集。
为了使其支持多线程,需要在每个线程中增加支持ITIMER_PROF信号的桩函数,感兴趣的可以去网上搜索相关资料。
3、必须保证程序正常结束,否则无法生成gmon.out文件
应用程序的崩溃、非主程序退出、忽略SIGPROF信号或者运行时间非常短,也即低于10毫秒,则会产生这种现象。同样在虚拟机中运行(本次未有出现),也有可能出现这种情况。对于运行时间过短的,可以在应用程序结束位置增加类似下面的代码来获得gmon.out文件:
static void sighandler( int sig_no )
{
exit(0);
}
signal( SIGUSR1, sighandler );
这样,在使用kill -USR1 pid 后,同样会生成分析文件gmon.out.
三、例程
在原有的例程基础上修改一下:
#include <iostream>
using namespace std;
void t1()
{
int i = 0;
while (i < 1000)
{
i++;
}
}
void t2()
{
int i = 0;
while (i < 2000)
{
i++;
}
}
void t3()
{
for (int i = 0; i < 100000; ++i)
{
t1();
t2();
}
}
int main()
{
t3();
printf("OK!");
return 0;
}
执行编译成功的应用程序,即可得到gmon.out文件。然后就可以使用命令分析相关信息:
f:~/gprof$ gprof ./test_gprof gmon.out|less -S
Flat profile:
Each sample counts as 0.01 seconds.
% cumulative self self total
time seconds seconds calls ms/call ms/call name
47.21 0.20 0.20 100000 0.00 0.00 t2()
37.76 0.37 0.16 100000 0.00 0.00 t1()
0.00 0.37 0.00 1 0.00 0.00 _GLOBAL__sub_I__Z2t1v
0.00 0.37 0.00 1 0.00 365.37 t3()
0.00 0.37 0.00 1 0.00 0.00 __static_initialization_and_destruction_0(int, int)
% 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.
^L
Copyright (C) 2012-2020 Free Software Foundation, Inc.
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved.
^L
Call graph (explanation follows)
granularity: each sample hit covers 2 byte(s) for 2.74% of 0.37 seconds
index % time self children called name
<spontaneous>
[1] 100.0 0.00 0.37 main [1]
0.00 0.37 1/1 t3() [2]
-----------------------------------------------
0.00 0.37 1/1 main [1]
[2] 100.0 0.00 0.37 1 t3() [2]
0.20 0.00 100000/100000 t2() [3]
0.16 0.00 100000/100000 t1() [4]
-----------------------------------------------
0.20 0.00 100000/100000 t3() [2]
[3] 55.6 0.20 0.00 100000 t2() [3]
-----------------------------------------------
0.16 0.00 100000/100000 t3() [2]
.......
转成图像分析:
f:~/gprof$ gprof ./test_gprof gmon.out|gprof2dot |dot -T png -o t.png
四、总结
gprof用起来不如gperftools爽,但总是有胜于无吧。估计大佬们会继续更新完善,后续就会越来越好用。工具有很多种,哪种用得方便,就用哪个,以实现目的为目标,不能僵化教条。一定要明白的是,工具是为开发服务的,而不是增加开发的难度的。