使用gprof测量程序运行时间

news/2024/5/18 22:29:11 标签: profiling, function, gcc, graph, profiler, signal

gprof使用详细介绍 linuxc/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 显示使用次数为零的例程(按照调用计数和累积时间计算)。


http://www.niftyadmin.cn/n/739429.html

相关文章

谈谈重载(overload)覆盖(override)与隐藏、多态

摘自http://blog.csdn.net/yanjun_1982/archive/2005/09/02/470405.aspx 这三个概念都是与OO中的多态有关系的。如果单是区别重载与覆盖这两个概念是比较容易的&#xff0c;但是隐藏这一概念却使问题变得有点复杂了&#xff0c;下面说说它们的区别吧。 重载是指不同的函…

Apache模块开发

参考&#xff1a;http://blog.csdn.net/deally/article/details/4290842 第一步 使用采用Apache只带的工具apxs产生一个模板Helloword模块 apxs -g -n hello这样就会在当前目录产生一个Hello文件夹进入hello文件夹&#xff0c;修改mod_hello.c文件 里面有hello_handler函数&am…

PELCO-D与PELCO-P协议介绍

摘自http://guojun0681.blog.163.com/blog/static/10051312008920104153565/ PELCO-D与PELCO-P协议介绍 一般控制协议都由硬件或软件商编制在程序里面&#xff0c;我们只需要通过相关的控制设备来进行操作。但是作为一个从事监控行业的技术人员&#xff0c;往往会遇到除了电脑…

ap_hook_handler的定义在哪?

近日在看apache的源码&#xff0c;在他的module的定义中&#xff0c;ap_hook_handler是一个非常重要的函数。用来在apache中注册你的自定义module中的callback函数。 遍搜ap_hook_handler&#xff0c;寻不得在哪定义的。最后发现&#xff0c;这家伙把所有的hook函数都定义在宏里…

Find命令用法

Find命令用法 %find . ctime 0 -print //搜尋今天修改過的所有檔 %find . -name *.bak -exec rm {}\ //搜尋加刪除 %find . \(-name *.txt -ctime 7\) -print //搜尋7天前修改過的txt檔 利用Find命令改變所有權&#xff0c;想要改變當前目錄下所有檔的所有權,可以這樣: fi…

转:编写跨平台的软件入门——有关字节对齐

标题&#xff1a;编写跨平台的软件入门——有关字节对齐2008-03-18 09:40:29一&#xff0c; 为什么要跨平台&#xff1f;你想过把你的 Windows 上编写的程序在 Linux 编译运行吗&#xff0c;以及在 Mac 或其他 OS 上运行等等&#xff1f;反过来也一样&#xff1f;这…

phpMyadmin忘记密码解决办法

登陆mysql #mysql -uroot mysql mysql>UPDATE user SET PasswordPASSWORD(123456) where USERroot; mysql>FLUSH PRIVILEGES; mysql>quit #> service mysqld stop #> service mysqld start

同步对象Event的用法

首先介绍CreateEvent是创建windows事件的意思&#xff0c;作用主要用在判断线程退出&#xff0c;线程锁定方面. CreateEvent函数功能描述&#xff1a;创建或打开一个命名的或无名的事件对象.EVENT有两种状态&#xff1a;发信号&#xff0c;不发信号。 SetEvent/ResetEvent分别…