AIX命令参考大全,卷 2,d - h - gprof 命令

[ 页的底部 | 上一页 | 下一页 | 目录 | 索引 | 法律条款 ]

AIX命令参考大全,卷 2,d - h

gprof 命令

用途

显示调用图概要分析数据

语法

/usr/ucb/gprof [ -b ] [ -e Name ] [ -E Name ] [ -f Name ] [ -F Name ] [ -L PathName ] [ -s ] [ -z] [ a.out [ gmon.out ... ] ]

描述

gprof 命令可生成 C、Pascal、FORTRAN 或 COBOL 程序的执行概要文件。被调用的例程的结果合并到各个调用程序的概要文件中。gprof 命令有助于标识程序如何消耗 CPU 资源量。要了解程序的哪些功能(例程)正在使用 CPU,您可以用 gprof 命令对该程序进行概要分析。

概要数据可从调用图概要文件(缺省状态下为 gmon.out)中获取,这些程序是由使用 -pg 选项的 cc 命令编译的程序创建的。-pg 选项链接在为概要分析而编译的各种版本的库例程中,且它读取指定的对象文件(缺省情况下为 a.out)中的符号表,并将该符号表与调用图概要文件相关联。如果指定了多个概要文件,gprof 命令的输出显示给定概要文件中的概要信息的总结。

-pg 选项可使编译器在为程序中每个重新编译的函数生成的对象代码中插入对 mcount 子例程的调用。在程序执行期间,每当父函数调用子函数时,子函数都会调用 mcount 子例程来使用于该父-子函数对的独特计数器加 1。在不是使用 -pg 选项重新编译的程序中不会插入 mcount 子例程,因此也就不会保持是谁调用它们的记录。

注意:来自 C++ 对象文件的符号在使用之前将其名称解码(demangle)。

gprof 命令将得到三项结果:

  1. 首先是会得到类似于 prof 命令所提供的平面概要文件。此列表按照递减的时间顺序给出了程序中每个函数的总执行时间和调用计数。这些时间随后沿调用图边界传播。由此可以找到执行周期,从而使处于同一周期中的调用共享该周期的时间。
  2. 第二个列表显示了按照各自存在的时间排序的功能,包括其调用图后代的时间。在每个功能项的下方列出了其(直接)调用图的子代,并附有如何将它们的时间传播到此功能的指示。在此函数的上方类似地显示了如何将此函数及其后代的时间传播给它的(直接)调用图父代。
  3. 同时还显示了周期,包括整个周期项和该周期的成员列表以及这些成员在该周期中占用的时间和调用次数。

使用 fork 和 exec 子例程时的概要分析

如果程序在多个并发的进程中运行了 forkexec 子例程时,使用 gprof 命令进行概要分析会存在一些问题。概要是每个进程的环境属性,因此,如果对其进行概要分析的进程又派生出新进程,则此子进程也会被列入分析的范畴。然而,这样一来两个进程都向运行父进程的目录中的 gmon.out 文件写入,从而导致它们其中的写入内容被覆盖。因此,对于多进程概要分析,推荐您使用 tprof 命令。

如果必须使用 gprof 命令,绕过上述问题的一个方法是调用 chdir 子例程更改子进程的当前目录。这样一来,当子进程退出时,其 gmon.out 文件就会被写入到新的目录。下列示例演示了这种方法:

cd /u/test   # current directory containing forker.c program
pg forker.c
main()
{
int i, pid;
static char path[]="/u/test2";
pid=fork();             /* fork a child process */
if(pid==0) {            /* Ok, this is the child process */
   chdir (path);        /* create new home directory so
                           gmon.out isn't clobbered! */
   for (i=0; i<30000; i++) sub2();  /* 30000 calls to sub2
                                       in child profile */
   }
else                   /* Parent process... leave gmon.out
                          in current directory */
   for (i=0;i<1000; i++) sub1(pid);   /* 1000 calls to sub1
                                         in parent profile */
}
int sub1(pid)   /* silly little function #1, called
                   by parent 1000 times */
int pid;
{
int i;
printf("I'm the parent, child pid is %i.\n",pid);
}
int sub2()     /* silly little function #2, called
                  by child 30,000 times */
{
printf("I'm the child.\n");
}
cc -pg forker.c -o forker   # compile the program
mkdir /u/test2              # create a directory for childi
                              to write gmon.out in
forker >/dev/null           # Throw away forker's many,
                              useless output lines
gprof forker   >parent.out  # Parent process's gmon.out is
                              in current directory
gprof forker ../test2/gmon.out >child.out
                            # Child's gmon.out is in test2
                              directory

此时,如果将 test 目录中的 parent.outchild.out 这两个 gprof 命令的输出列表进行比较,您可以看到 sub1 子例程在父进程中调用了 1,000 次,在子进程中调用了 0 次,而 sub2 子例程在子进程中调用了 30,000 次,在父进程中调用了 0 次。

运行 exec 子例程的进程不继承概要分析。然而,如果由 exec 子例程执行的程序是使用 -pg 选项编译的,则此程序应进行概要分析。就拿前面的 forker.c 示例来说,如果同时对父进程和由 exec 子例程程序运行的程序进行概要分析,则其中一个会覆盖另外一个的 gmon.out 文件,除非对其中之一中使用 chdir 子例程。

在没有源代码的情况下进行概要分析

如果没有程序的源代码,您可以在不重新编译的情况下使用 gprof 命令进行概要分析。然而,您必须能通过相应的编译程序命令(例如,用于 C 语言的 cc 命令)重新链接程序模块。如果不作重新编译,您将无法获得调用频率计数,尽管平面概要文件在没有它们的情况下仍然有用。作为额外的补偿,您的程序会以与平常大致相同的速度运行。下面说明了如何进行概要分析:

cc -c dhry.c         # Create dhry.o without call counting code.
cc -pg dhry.o -L/lib -L/usr/lib -o dhryfast
                     # Re-link (and avoid -pg libraries).
dhryfast             # Create gmon.out without call counts.
gprof >dhryfast.out  # You get an error message about no call counts
                     #  -- ignore it.

在不调用计数的情况下运行时,一些快速执行的功能根本不会显示在列表中(但您知道必须要调用它们)。尽管不可见,但这个结果对 gprof 命令而言是正常的。gprof 命令仅列出了那些至少调用一次或每个时钟周期至少注册一次的功能。虽然快速执行函数也运行,但快速执行功能通常不会接收任何时钟周期。由于暂挂了调用计数功能,因此这些小函数不会被列出。(如果在 cc -pg 命令行中省略了 -L 选项,您可以获得运行时例程的调用计数。)

使用更少的实内存

由于 -pg 选项专用相当于程序文本大小一半的固定实时内存缓冲区,因此使用 gprof 命令进行概要分析时可能导致程序过度分页。过度分页不会影响概要分析所生成的数据,原因是被分析的程序在等待 I/O 时不生成时钟周期(它仅在使用 CPU 时才这样做)。如果因为过度分页而导致的时间延迟是不可接受的,建议您使用 tprof 命令。

标志

-b 禁止打印概要文件中每个字段的描述。
-E Name 禁止打印例程 Name 及其子代的图表概要文件项,此标志类似于 -e 标志,但它在总时间和百分比时间的计算中排除了由例程 Name 及其子代所用的时间。(-E MonitorCount -E MonitorCleanup 为缺省值。)
-e Name 禁止打印例程 Name 及其所有子代的图表概要文件项(除非它们有未被限制的其它祖先)。可以给定多个 -e 标志。一个 -e 标志只能指定一个例程。
-F Name 打印例程 Name 及其子代的图表概要文件项,它类似于 -f 标志,但它在总时间和百分比时间计算中仅使用所打印的例程的时间。可以指定多个 -F 标志。一个 -F 标志只能指定一个例程。-F 标志覆盖 -E 标志。
-f Name 打印指定的例程 Name 及其子代的图表概要文件项。可以指定多个 -f 标志。一个 -f 标志只能指定一个例程。
-L PathName 使用备用的路径名定位共享对象。
-s 生成表示所有指定的概要文件中的概要分析信息的总结的 gmon.sum 概要文件。这个总结性的概要文件可以提供给 gprof 命令的后继执行(使用 -s 标志),从而可将数次运行 a.out 文件的概要分析数据累积起来。
-z 显示使用次数为零的例程(按照调用计数和累积时间的指示)。

示例

  1. 要获得概要分析输出,可输入:

    gprof
  2. 要获取先前运行的命令的概要分析输出(现在可能已移走),可输入:

    gprof -L/home/score/lib runfile runfile.gmon

    本示例使用给定的 runfile.gmon 文件作为样本数据和 runfile 文件作为本地符号,检查 /u/score/lib 文件中的可加载对象。

  3. 对样本程序 dhry.c 进行概要分析:
    1. 按以下所述,使用 cc -pg 命令重新编译该应用程序:

      cc -pg dhry.c -o dhry # Re-compile to produce gprof output.
    2. 运行重新编译后的程序。在当前的工作目录(而不是该程序的可执行文件所驻留的目录)中创建名为 gmon.out 的文件。

      dhry    # 执行程序以生成 ./gmon.out 文件。
    3. 在包含 gmon.out 文件的目录中运行 gprof 命令,生成 CALL-GRAPH 和 FLAT PROFILE 报告。

      gprof >gprof.out     # 按照您的喜好为报告命名
      vi gprof.out         # 首先读取平面概要文件。

gprof 命令的通篇描述中,大部分示例都使用了 C 程序 dhry.c。但是,只要将 C 编译器和 cc 替换成相应的编译器名称,并将 function 一词替换成 subroutine,则关于这些示例的讨论也同样适用于 FORTRAN、Pascal 或 COBOL 模块。例如,下列命令即显示了如何对名为 matrix.f 的 FORTRAN 程序进行概要分析:

xlf -pg matrix.f -o matrix # 对 matrix.f 程序进行 FORTRAN 样式的编译
matrix                    # 执行 gprof 概要分析,
                          #   并生成 gmon.out 文件
gprof > matrix.out        # 在 matrix.out 中生成来自 gmon.out
                          #   的概要分析报告
vi matrix.out             # 首先读取平面概要文件。

文件

a.out 名称列表和文本空间
gmon.out 动态调用图和概要文件
gmon.sum 动态调用图和概要文件总结
/usr/ucb/gprof 包含 gprof 命令。

相关信息

cc 命令、prof 命令。

exit 子例程、monitor 子例程、profil 子例程。

《AIX 5L V5.2 性能管理指南》中的『性能监视与调整命令和子例程』

《AIX 5L V5.2 系统用户指南:操作系统与设备》中的『命令概述』

AIX 5L Version 5.2 General Programming Concepts: Writing and Debugging Programs中的『子例程概述』

[ 页的顶部 | 上一页 | 下一页 | 目录 | 索引 | 法律条款 ]