英文参考:http://sourceware.org/binutils/docs-2.17/gprof/
转载自http://www.cnblogs.com/huangpeng/archive/2009/02/17/1392456.html
程序分析工具gprof介绍
程序分析是以某种语言书写的程序为对象,对其内部的运作流程进行分析。程序分析的目的主要有三 点:一是通过程序内部各个模块之间的调用关系,整体上把握程序的运行流程,从而更好地理解程序,从中汲取有价值的内容。二是以系统优化为目的,通过对程序 中关键函数的跟踪或者运行时信息的统计,找到系统性能的瓶颈,从而采取进一步行动对程序进行优化。最后一点,程序分析也有可能用于系统测试和程序调试中。 当系统跟踪起来比较复杂,而某个BUG又比较难找时,可以通过一些特殊的数据构造一个测试用例,然后将分析到的函数调用关系和运行时实际 的函数调用关系进行对比,从而找出错误代码的位置。
程序分析工具不同于调试器,它只产生程序运行时某些函数的调用次数、执行时间等等宏观信息,而不 是每条语句执行时的详细信息。Gprof是Linux下一个强有力的程序分析工具。对于C、Pascal或者Fortran77语言的程序,它能够以“日志”的形式记录程序运行时的统计信息:程序运行中各个函数消耗的时间和 函数调用关系,以及每个函数被调用的次数等等。从而可以帮助程序员找出众多函数中耗时最多的函数,也可以帮助程序员分析程序的运行流程。相信这些功能对于 分析开源代码的程序员来说,有着相当大的诱惑力。
用gprof分析程序
用gprof对程序进行分析主要分以下三个步骤:
l 用编译器对程序进行编译,加上-pg参数。
l 运行编译后的程序。
l 用gprof命令查看程序的运行时信息。
先以一个简单的例子演示一下吧。随便找一个能够运行的程序的源代码,比如下面的文件test.c:
2 int IsEven(int x)
3
4 {
5
6 return 0 == x & 1;
7
8 }
9
10 int main(int argc, char *argv[]
11
12 {
13
14 int i = 0;
15
16 while(++i < 1000) IsEven(i);
17
18 }
首先,用以下命令进行编译:
[root@localhost]#gcc –o test –pg test.c
然后,运行可执行文件test.
[root@localhost]#./test
运行后,在当前目录下将生成一个文件gmon.out,这就是gprof生成的文件,保存有程序运行期间函数调用等信息。
最后,用gprof命令查看gmon.out保存的信息:
[root@localhost]#gprof test gmon.out –b
这样就有一大堆信息输出到屏幕上,有函数执行单间,函数调用关系图等等,如下:
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 1000 0.00 0.00 IsEven(int)
Call graph
granularity: each sample hit covers 2 byte(s) no time propagated
index % time self children called name
0.00 0.00 1000/1000 main [7]
[8] 0.0 0.00 0.00 1000 IsEven(int) [8]
-----------------------------------------------
Index by function name
[8] IsEven(int)
以上介绍了gprof最简单的使用方法,下面针对其使用过程中的三个步骤详细说明。
编译和链接
上面的例子中,程序比较简单,只有一个文件。如果源代码有多个文件,或者代码结构比较复杂,编译 过程中先生成若干个目标文件, 然后又由链接器将这些目标文件链接到一起,这时该怎么使用gprof呢?
对于由多个源文件组成的程序,编译时需要在生成每个.o文件的时候加上-pg参数,同时在链接的时候也要加上-pg参数。对于链接器不是GCC的情况,如ld,又有特殊的要求。
同时,-pg参数只能记录源代码中各个函数的调用关系,而不能记录库函数的调用情况。要想记录每个库函数的调用 情况,链接的时候必须指定库函数的动态(或者静态)链接库libc_p.a,即加上-lc_p,而不是-lc。
还要说明的是,如果有一部分代码在编译时指定了-pg参数,而另一部分代码没有指定,则生 成的gmon.out文件中将缺少一部分函数,也没有那些函数的调用关系。但是并不影响gprof对其它函数进行记录。
运行
编译好的程序运行时和运行一般的程序没有什么不同,只是比正常的程序多生成了一个文件gmon.out。注意,这个文件名是固 定的,没法通过参数的设置进行改变。如果程序目录中已经有一个gmon.out,则它会被新的gmon.out覆盖掉。
关于生成的gmon.out文件所在的目录,也有以下约定:程序退出时所运行的文件所在目录就是生成的gmon.out文件所在的目录。如果一 个程序执行过程中调用了另一个程序,并在另一个程序的运行中终止,则gmon.out会在另一个程序所在的目录中生成。
还有一点要注意的就是当程序非正常终止时不会生成gmon.out文件,也因此就没法查看程 序运行时的信息。只有当程序从main函数中正常退出,或者通过系统调用exit()函数而退出时,才会生成gmon.out文件。而通过底层调用如_exit()等退出时不会生成gmon.out。
查看
查看程序运行信息的命令是gprof,它以gmon.out文件作为输入,也就是将gmon.out文件翻译成可读的形式展现给用户。其命令格式如下:
gprof [可执行文件] [gmon.out文件] [其它参数]
方括号中的内容可以省略。如果省略了“可执行文件”,gprof会在当前目录下搜索a.out文件作为可执行文件,而如果省 略了gmon.out文件,gprof也会在当前目录下寻找gmon.out。其它参数可以控制gprof输出内容的格式等信息。最常用的参数如下:
l -b 不再输出 统计图表中每个字段的详细描述。
l -p 只输出函 数的调用图(Call graph的那部分信息)。
l -q 只输出函 数的时间消耗列表。
l -e Name 不 再输出函数Name 及其子函数的调用图(除非它们有未被限制 的其它父函数)。可以给定多个 -e 标志。 一个 -e 标志只能指定一个函数。
l -E Name 不 再输出函数Name 及其子函数的调用图,此标志类似于 -e 标志,但它在总时间和百分比时间的计算中排除了由函数Name 及其子函数所用的时间。
l -f Name 输 出函数Name 及其子函数的调用图。可以指定多个 -f 标志。一个 -f 标志只能指定一个函数。
l -F Name 输 出函数Name 及其子函数的调用图,它类似于 -f 标志,但它在总时间和百分比时间计算中仅使用所打印的例程的时间。可 以指定多个 -F 标志。一个 -F 标志只能指定一个函数。-F 标志覆盖 -E 标志。
l -z 显示使用 次数为零的例程(按照调用计数和累积时间计算)。
不 过,gprof不能显示对象之间的继承关系,这也是它的弱点.
转载自:http://os.51cto.com/art/200703/41426_2.htm
生成图形化的函数调用图
1.Graphviz 工具
看到这里你也可能觉得上面的函数调用图实在是不方便察看,也看不出来一个程序调用的整体框架。没有关系,我再介 绍一个有用的工具给你,使用 Graphviz,Graphviz or Graph Visualization 是由 AT&T 开发的一个开源的图形可视化工具。它提供了多种画图能力,但是我们重点关注的是它使用 Dot 语言直连图的能力。在这里,将简单介绍如何使用 Dot 来创建一个图形,并展示如何将分析数据转换成 Graphviz 可以使用的规范, Dot 使用的图形规范。
使用 Dot 语言,你可以指定三种对象:图、节点和边。为了让你理解这些对象的含义,我将构建一个例子来展示这些元素的用法。
下图给出了一个简单的定向图 (directed graph),其中包含 3 个节点。第一行声明这个图为 G,并且声明了该图的类型(digraph)。接下来的三行代码用于创建该图的节点,这些节点分别名为 node1、node2 和 node3。节点是在它们的名字出现在图规范中时创建的。边是在在两个节点使用边操作(->)连接在一起时创建的,如第 6 行到第 8 行所示。我还对边使用了一个可选的属性 label,用它来表示边在图中的名称。最后,在第 9 行完成对该图规范的定义。
使用 Dot 符号表示的示例图(test.dot)
1: digraph G { |
要 将这个 .dot 文件转换成一个图形映像,则需要使用 Dot 工具,这个工具是在 Graphviz 包中提供的。清单 6 介绍了这种转换。
清 单 6. 使用 Dot 来创建 JPG 映像
[linux /home]$ dot -Tjpg test.dot -o test.jpg
在 这段代码中,我告诉 Dot 使用 test.dot 图形规范,并生成一个 JPG 图像,将其保存在文件 test.jpg 中。所生成的图像如图1所示。在此处,我使用了 JPG 格式,但是 Dot 工具也可以支持其他格式,其中包括 GIF、PNG 和 postscript等等。
![]() |
图 1. Dot 创建的示例图 |
Dot 语言还可以支持其他一些选项,包括外形、颜色和很多属性。有兴趣可以查看graphviz相关文档。
2.从gprof的输出中提取调用图信息, 产生可供Graphviz使用的dot文件。
这样的脚本有人已经实现了,我们只要下载一个现成的就可以了,首先从http://www.ioplex.com/~miallen/ 网站下载一个mkgraph脚本。解压该脚本到包含gmon.out文件的目录下。使用mkgraph0.sh产生调用的jpg图像文件。例如:使用上面 的例子,生成cflow的调用图。
[linux /home/cflow-1.1/src]$ mkgraph0.sh cflow gmon.out
部分调用图如下,有了这个图是不是对程序整体框架有了个清晰地了解,如果你对生成的调用图效果不满意,你还可以通过修改 mkgraph0脚本使之产生合适的dot文件即可:
![]() |
部分调用图如下 |
总 结:
使用gprof , Graphviz , mkgraph 生成函数调用图
1. 使用 -pg 编译和链接你的应用程序。
2. 执行你的应用程序使之生成供gprof 分析的数据。
3. 使用mkgraph脚本生成图形化的函数调用图。
相关资料:
文档:用 Graphviz 可视化函数调用
文档:Speed your code with the GNU profiler
文档:gropf 帮助文件
Mkgraph 脚本:http://www.ioplex.com/~miallen/
Graphviz 工具:http://www.graphviz.org
Cflow :http://www.gnu.org/software/cflow/
转载自:http://www.51testing.com/?uid-13997-action-viewspace-itemid-79952
1 下载
http://code.google.com/p/jrfonseca/wiki/Gprof2Dot
http://jrfonseca.googlecode.com/svn/trunk/gprof2dot/gprof2dot.py 下载gprof2dot.py
http://www.graphviz.org/Download_source.php下载源代码graphviz-2.18.tar.gz
2 环境
[admin@b2bsearch80 bin]$ python -V
Python2.3.4
[admin@b2bsearch80 bin]$ gcc -v
Reading specs from /usr/lib/gcc/i386-redhat-linux/3.4.6/specs
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --disable-checking --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-java-awt=gtk --host=i386-redhat-linux
Thread model: posix
gcc version 3.4.6 20060404 (Red Hat3.4.6-3)
[admin@b2bsearch80 bin]$ uname -a
Linux b2bsearch802.6.9-42.ELsmp #1 SMP Wed Jul 12 23:27:17 EDT 2006 i686 i686 i386 GNU/Linux
3 安装
Chmod 744 gprof2dot.py
Tar -zxvf graphviz-2.18.tar.gz
./configure
make
su -
make install
4 编译代码
gcc -pg -g -o uniqueCoreDump uniqueCoreDump.c
5 执行代码生成gmon.out
执行命令产生gmon.out文件
./uniqueCoreDump
ll gmon.out
如果gprof ./uniqueCoreDump有:
gmon.out file is missing call-graph data
则表示没有正确的编译选项或者只有一个main函 数
6 生成图片
gprof ./uniqueCoreDump | ./gprof2dot.py -n0 -e0 | dot -Tpng -o output.png
sz output.png