您的位置:首页 > 其它

使用gprof测量程序运行时间

2012-07-20 23:13 344 查看
gprof使用详细介绍 linux下c/c++编程

gprof介绍

gprof是GNU profiler工具。可以显示程序运行的“flat profile”,包括每个函数的调用次数,每个函数消耗的处理器时间。也可以显示“调用图”,包括函数的调用关系,每个函数调用花费了多少时间。还可以显示“注释的源代码”,是程序源代码的一个复本,标记有程序中每行代码的执行次数。

基本用法:
1. 使用-pg选项编译和链接你的应用程序。 gcc -pg -g -o test test.c

2. 执行你的应用程序,使之运行完成后生成供gprof分析的数据文件(默认是gmon.out)。

3. 使用gprof程序分析你的应用程序生成的数据,例如:gprof a.out gmon.out。


程序如下:
#include <stdio.h>

#include <sys/time.h>

#include <time.h>

#include <string.h>

	

int testT(int i)

{

    printf("%d\n", i*i);    

}

void a()

{

    printf("\t\t+---call a \n");

}

void b()

{

    printf("\t\t+---call b \n");

}

void c()

{

    printf("\t\t+---call c \n");

    a();

    b();

    return 0;

}

int main(){

    testT(1);

    c();

	return 0;

}


举例

gcc -Wall -pg -o test test.c //程序文件名称 test.c 编译时使用 -pg

现在我们可以再次运行test,并使用我们前面使用的测试数据。这次我们运行的时候,test运行的分析数据会被搜集并保存在'gmon.out'文件中,我们可以通过运行 ' gprof test '来查看结果。

./test

gprof test

gprof 实现原理:

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

程序运行结束后,会在程序退出的路径下生成一个 gmon.out文件。这个文件就是记录并保存下来的监控数据。可以通过命令行方式的gprof或图形化的Kprof来解读这些数据并对程序的性能进行分析。

另外,如果想查看库函数的profiling,需要在编译是再加入“-lc_p”编译参数代替“-lc”编译参数,这样程序会链接libc_p.a 库,才可以产生库函数的profiling信息。如果想执行一行一行的profiling,还需要加入“-g”编译参数。

gprof产生的信息

% the percentage of the total running time of the

time program used by this function.

cumulative a running sumof 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.

每一次调用花费在函数的时间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. 在内存中分配一些内存,存储程序执行期间的统计数据

2. 在GCC使用-pg选项编译后,gcc会在程序的入口处(main 函数之前)调用

void monstartup(lowpc, highpc)

在每个函数的入口处调用

void _mcount()

在程序退出时(在 atexit () 里)调用

void _mcleanup()

* monstartup:负责初始化profile环境,分配内存空间

* _mcount: 记录每个函数代码的caller和callee的位置

* _mcleanup:清除profile环境,保存结果数据为gmon.out,供gprof分析结果

3.在_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 显示使用次数为零的例程(按照调用计数和累积时间计算)。

使用注意:

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文件。

编辑

其他 C/C++ 程序分析器

还有其他很多分析器可以使用gprof 的数据, 例如KProf (截屏) 和 cgprof。虽然图形界面的看起来更舒服,但我个人认为命令行的gprof 使用更方便。

为了您的安全,请只打开来源可靠的网址
打开网站 取消
来自:
http://hi.baidu.com/zojoyo/blog/item/0ad631ee9aee302e2cf5341f.html


同时,-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 显示使用次数为零的例程(按照调用计数和累积时间计算)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: