如何在Linux上安装和使用分析工具Gprof

毫无疑问,测试是软件开发过程中不可或缺的重要组成部分之一。 通过测试,我们并不只是测试错误的代码 - 当然,错误检测非常重要,因为没有人会希望他们的软件是错误的 - 代码的性能也同样重要。

如果分解到最后一点,性能测试可以有效地测试特定代码片段(例如功能)消耗的时间。 通常情况下,功能或一组功能可以对应于软件的许多特征之一。 所以,如果通过性能测试,我们可以在代码中增强这些功能的性能,使软件的整体性能变得更好。

如果您是程序员,谁编写C,Pascal或Fortran77编程语言的代码,并使用Linux作为开发平台,您将很高兴地知道,存在一个强大的工具,您可以通过它检查代码的性能 - 该工具是Gprof 。 在本教程中,我们将讨论如何下载,安装和使用此工具的详细信息。

在我们向前推进之前,请注意,本教程中提到的所有示例和说明都已在Ubuntu 14.04LTS上进行了测试,所用的Gprof版本为2.24。

什么是Gprof?

那么,Gprof究竟是什么? 根据该工具的官方文档,它为用户提供了C,Pascal或Fortran77程序的执行概要文件。 Gprof基本上做的是,它计算每个例程或功能中花费的时间。 “接下来,这些时间沿着调用图的边缘传播,循环被发现,并且调用一个循环来共享循环的时间。

如果这一切听起来有点混乱(特别是报价部分),别担心,我们将通过一个例子弄清楚事情。 所以,继续阅读

下载并安装Gprof

首先检查工具是否已经安装在系统上。 为此,只需在终端中运行以下命令即可。

$ gprof

如果您收到以下错误:

$ a.out: No such file or directory

那么这意味着该工具已经安装。 否则可以使用以下命令安装它:

$ apt-get install binutils

Gprof使用

不用说,理解Gprof这个工具的最好方法就是通过一个实际的例子。 所以,我们将从一个C语言程序开始,我们将通过Gprof进行剖析。 这是程序:

//test_gprof.c

#include<stdio.h>

void func4(void)
{
    printf("\n Inside func4() \n");
    for(int count=0;count<=0XFFFF;count++);
}

void func3(void)
{
    printf("\n Inside func3() \n");
    for(int count=0;count<=0XFFFFFFF;count++);
}

void func2(void)
{
    printf("\n Inside func2() \n");

    for(int count=0;count<=0XFFF;count++);

    func3();
}

void func1(void)
{
    printf("\n Inside func1() \n");
    for(int count=0;count<=0XFFFFFF;count++);

    func2();
}

int main(void)
{
    printf("\n main() starts...\n");
    for(int count=0;count<=0XFFFFF;count++);

    func1();
    func4();
    printf("\n main() ends...\n");

    return 0;
}

请注意,上面显示的代码( test_gprof.c )专门用于说明Gprof - 它不是从任何现实的项目中获取的。

现在,继续下一步是使用gcc编译这段代码。 注意,理想情况下,我将使用以下命令编译上述代码:

$ gcc -Wall -std=c99 test_gprof.c -o test_gprof

但是由于我们必须使用Gprof配置代码,所以我必须使用gcc编译器提供的-pg命令行选项。 所以,命令变成:

$ gcc -Wall -std=c99 -pg test_gprof.c -o test_gprof

如果您看看gcc的手册页,这里是关于-pg选项的内容:

“生成额外的代码来编写适合于分析程序gprof的配置文件信息。在编译需要数据的源文件时必须使用此选项,并且还必须在链接时使用它。

现在,回到上面的命令,成功执行后,将在输出中生成一个名为test_gprof的二进制文件。 下一步是启动该可执行文件。 以下是我在这种情况下启动二进制文件的方法:

$ ./test_gprof

一旦执行命令,您将看到将在当前工作目录中生成名为gmon.out的文件。

$ ls gmon*
gmon.out


该文件包含Gprof工具所需的所有信息,用于生成可读取的分析数据。 所以,现在使用Gprof工具如下:

$ gprof test_gprof gmon.out > profile-data.txt

基本上,这个命令的通用语法是:

$ gprof [executable-name] gmon.out > [name-of-file-that-will-contain-profiling-data]

现在,在我们看到profile-data.txt文件包含的信息之前,值得一提的是,Gprof生成的可读输出分为两部分:平面配置文件和调用图。 以下是Gprof的手册页面关于这两个部分的信息:

“平面配置文件显示了您的程序在每个功能中花费了多少时间,以及调用多少次功能。如果您只想知道哪些功能可以烧录大部分的周期,那么这里就简明扼要。

“调用图显示了对于每个函数,调用哪个函数,它调用了哪些其他函数,以及多少次。还有一个估计是在每个函数的子例程中花费了多少时间,这可以建议你所在的地方可能会尝试消除使用大量时间的函数调用。

掌握了这些信息,现在,您将能够更好地了解您的分析输出文件(我的案例中的profile-data.txt)中存在的数据。 以下是我案中的平面资料:

Flat profile:

Each sample counts as 0.01 seconds.
% cumulative self self total
time seconds seconds calls ms/call ms/call name
96.43 0.81 0.81 1 810.00 810.00 func3
3.57 0.84 0.03 1 30.00 840.00 func1
0.00 0.84 0.00 1 0.00 810.00 func2
0.00 0.84 0.00 1 0.00 0.00 func4

这就是每个领域的意义:

继续下去,这是我的情况下的通话图:

Call graph (explanation follows)


granularity: each sample hit covers 4 byte(s) for 1.19% of 0.84 seconds

index % time self children called name
0.03 0.81 1/1 main [2]
[1] 100.0 0.03 0.81 1 func1 [1]
0.00 0.81 1/1 func2 [3]
-----------------------------------------------
<spontaneous>
[2] 100.0 0.00 0.84 main [2]
0.03 0.81 1/1 func1 [1]
0.00 0.00 1/1 func4 [5]
-----------------------------------------------
0.00 0.81 1/1 func1 [1]
[3] 96.4 0.00 0.81 1 func2 [3]
0.81 0.00 1/1 func3 [4]
-----------------------------------------------
0.81 0.00 1/1 func2 [3]
[4] 96.4 0.81 0.00 1 func3 [4]
-----------------------------------------------
0.00 0.00 1/1 main [2]
[5] 0.0 0.00 0.00 1 func4 [5]

以下屏幕截图说明了信息调用图包含:

如果您想知道上述屏幕截图的来源,请告诉您,输出文件中包含所有这些信息的信息包括平面配置文件和调用图。 如果您希望从输出中省略此信息,可以使用Gprof提供的-b选项。

结论

不用说,我们刚刚在这里划伤了表面,因为Gprof提供了很多功能(只是看看其手册页 )。 但是,无论我们在这里所涵盖的内容应该足以让您开始。 如果您已经使用Gprof,并希望与所有人分享与该工具相关的内容,请点击下面的注释。

赞(52) 打赏
未经允许不得转载:优客志 » 系统运维
分享到:

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏