gprof性能测试工具使用分析

来源:互联网 发布:网络教老外学中文兼职 编辑:程序博客网 时间:2024/06/02 08:39

一 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  -gp -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) for 50.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( int sig_no )
{
      exit(0);
}
signal( SIGUSR1, sighandler );
当使用kill -USR1 pid 后,程序退出,生成gmon.out文件。