GNU Toolchain —— (六)gprof的应用

来源:互联网 发布:js跨域请求php 编辑:程序博客网 时间:2024/06/04 18:01

   gprof功能简介

  Gprof功能:打印出程序运行中各个函数消耗的时间,可以帮助程序员找出众多函数中耗时最多的函数。产生程序运行时候的函数调用关系,包括调用次数,可以帮助程序员分析程序的运行流程。

  有了函数的调用关系,这会让开发人员大大提高工作效率,不用费心地去一点点找出程序的运行流 程,这对小程序来说可能效果不是很明显,但对于有几万,几十万代码量的工程来说,效率是毋庸置疑的!而且这个功能对于维护旧代码或者是分析Open Source来说那是相当诱人的,有了调用图,对程序的运行框架也就有了一个大体了解,知道了程序的"骨架",分析它也就不会再那么茫然,尤其是对自己不 熟悉的代码和Open Source。费话不多说了,让我们开始我们的分析之旅吧!

   gprof实现原理

  通过在编译和链接你的程序的时候(使用 -pg 编译和链接选项),gcc 在你应用程序的每个函数中都加入了一个名为mcount ( or"_mcount" , or "__mcount" , 依赖于编译器或操作系统)的函数,也就是说你的应用程序里的每一个函数都会调用mcount, mcount 会在内存中保存一张函数调用图,并通过函数调用堆栈的形式查找子函数和父函数的地址。这张调用图也保存了所有与函数相关的调用时间,调用次数等等的所有信息。

  三 常用的gprof命令选项:

  -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 标志。

  -z 显示使用次数为零的例程(按照调用计数和累积时间计算)。

  四 尝试示例

  Test.c

  #include <stdio.h>

  int prime(int n)

  {

  int i;

  for (i=2; i<n; i++)

  {

  if (n%i == 0)

  return 0;

  return 1;

  }

  }

  void main(void)

  {

  int i, n;

  n = 1000;

  for (i=2; i<=n; i++)

  {

  if (prime(i))

  printf("%d/n", i);

  }

  }

  Gcc -pg -o test test.c

  ./test

  gprof -b test gmon.out |less

  Flat profile:

  Each sample counts as 0.01 seconds.

  % cumulative self self total

  time seconds seconds calls Ts/call Ts/call name

  100.00 0.02 0.02 main

  0.00 0.02 0.00 999 0.00 0.00 prime

  ^L

  Call graph

  granularity: each sample hit covers 4 byte(s) for50.00% of 0.02 seconds

  index % time self children called name

  <spontaneous>

  [1] 100.0 0.02 0.00 main [1]

  0.00 0.00 999/999 prime [2]

  -----------------------------------------------

  0.00 0.00 999/999 main [1]

  [2] 0.0 0.00 0.00 999 prime [2]

  -----------------------------------------------

  ^L

  Index by function name

  [1] main [2] prime

  五 使用注意:

  1) 一般gprof只能查看用户函数信息。如果想查看库函数的信息,需要在编译是再加入"-lc_p"编译参数代替"-lc"编译参数,这样程序会链接libc_p.a库,才可以产生库函数的profiling信息。

  2 gprof只能在程序正常结束退出之后才能生成程序测评报告,原因是gprof通过在atexit()里注册了一个函数来产生结果信息,任何非正常退出都不会执行atexit()的动作,所以不会产生gmon.out文件。如果你的程序是一个不会退出的服务程序,那就只有修改代码来达到目的。如果不想改变程序的运行方式,可以添加一个信号处理函数解决问题(这样对代码修改最少),例如:

  static void sighandler( intsig_no )

  {

  exit(0);

  }

  signal( SIGUSR1, sighandler )

  当使用kill -USR1 pid 后,程序退出,生成gmon.out文件。

  gprof产生的信息

  % the percentage of the total running time of the

  time program used by this function.

  函数使用时间占所有时间的百分比。

  cumulative a running sum of the number of secondsaccounted

  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 isprofiled,

  else blank.

  每一次调用花费在函数的时间microseconds

  total the average number of milliseconds spent in this

  ms/call function and its descendents per call, if this

  function is profiled, else blank.

  每一次调用,花费在函数及其衍生函数的平均时间microseconds

  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.

  函数名

词条图册更多图册

 

 

扩展阅读:

·  1

http://hi.baidu.com/msingle/blog/item/672b76d7e77315daa144df0f.html

·  2

http://blog.sina.com.cn/s/blog_48da903c0100bpmx.html

·  3

http://hi.baidu.com/gulunmuer/blog/item/5fa473863fc4123b66096e22.html

 

转自  http://baike.baidu.com/view/2100555.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)
Quote:
1: digraph G {

2: node1;

3: node2;

4: node3;

5:

6: node1 -> node2 [label="edge_1_2"];

7: node1 -> node3 [label="edge_1_3"];

8: node2 -> node3 [label="edge_2_3"];

9: }


要将这个 .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 和 post等等。


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文件即可:

 

转自  http://www.360doc.com/content/10/0429/11/474846_25401101.shtml