内容


用于 PowerPC 上的 Linux 的五个易用的性能分析工具

Comments

Performance Inspector

Performance Inspector 程序包中包括一套用于 Linux 的性能分析工具。这些工具可以用来分析您的 C/C++ 和 Java 应用程序 的性能,以及您的系统的整体性能。本文所涵盖的五个易用的工具是:

  • Timer Profiler(Tprof)
  • CPU utilization(AI)
  • Per thread time(PTT)
  • Java lock monitor(JLM)
  • Java heap dump(heap dump)

Performance Inspector 由 Tprof、AI、PTT、JLM、post、jprof、a2n、swtrace 和 heap dump 组成。

平台

当前,Performance Inspector 可用于运行在下列机器体系结构上的 SUSE United Linux 1.0 发行版本:i386、ia64、x86_64、ppc、ppc64、390x 和 s390。Performance Inspector 也可用于运行在这些机器体系结构上的另外的 Linux 发行版本。参阅 Performance Inspector 站点 以获得当前的详细情况。

对 PowerPC 机器体系结构(即 ppc 和 ppc 64)来说 ,Performance Inspector 只得到了 2.4.19 内核的支持,即 SUSE Linux Enterprise Server 8(SLES 8)所用的内核。代码正在被移植到 2.6 内核,所以您应该查看 Performance Inspector 站点以获得最新的信息。

收集性能分析数据

Performance Inspector 程序包包括一个内核补丁文件和一个驱动程序补丁文件。通过添加内核和驱动程序补丁、 重新编译内核并引导修补后的内核来完成 Performance Inspector 的安装。内核补丁是一个用于特定硬件的补丁, 将追踪挂钩(trace hooks)插入到内核例程中,比如 schedule、dispatch、interrupt、fork、exec、timer 和 vma 中。 驱动程序补丁中包含 Performance Inspector 设备驱动程序代码。内核追踪挂钩调用设备驱动程序代码中的函数, 那些函数将内核追踪挂钩在固定缓冲区(pinned buffer)中给出的信息记录下来。swtrace 等 Performance Inspector 工具与 驱动程序相互协作以利用存储在固定缓冲区中的信息。每个 CPU 有一个固定缓冲区。

下载并安装 Performance Inspector

您可以自 developerWorks Performance Inspector 下载 Performance Inspector 程序包。在 Performance Inspector 主页,点击 Downloads,然后点击链接以接受许可协议。 点击 common package(通用程序包)。当前的通用程序包名为 pi.package.2004-04-14.tar.gz。

安装程序包

Performance Inspector 处有安装 Performance Inspector 的完整说明,就在程序包下载链接后面。

下面的说明与 Web 站点上的说明相同,只是引入了一些针对 PowerPC 的特定内容。

  1. 您必须是 root 用户。要成为 root 用户,请输入命令 # su –
  2. 使用下面的命令在您的 Linux 机器上解开 Performance Inspector 程序包:
    # tar -xzf pi.package.2004-04-14.tar.gz

    如果程序包的名称已经更新,那么请使用新的程序包名。
  3. 解开程序包后将得到两个文件,即 piinstall 和 pi_tools.tar.gz。执行脚本 # ./piinstall

    运行这个脚本将创建出一个目录,默认情况下是 /piperf,然后将 pi_tools.tar.gz 文件解包到那个目录及其子目录中。如果您不想 接受 /piperf 这一默认值,脚本会允许您指定您自己的目录。

接下来,如果您想使用 Performance Inspector Java 工具,那么需要安装 Java。如果您不想使用 Java 工具,那么接下来 的步骤就是 修补、编译并引导内核

安装 Java

五个工具中的两个,即 JLM 和 heap dump,需要与 IBM 32 位和 64 位的 Runtime Environment for Linux v1.4.0 或者更新的版本一起使用。JLM 工具不能与非 IBM JVM 一起使用,因为这个工具使用了 IBM 对 JVM Profiler Interface(JVMPI)的扩展。heap dump 工具可以工作于其他非 IBM JVM,因为 它使用的只是标准的 JVMPI 事件。

IBM 的 32 位和 64 位 Runtime Environment for Linux 可以作为 IBM Developer Kit for Java 的一部分获得。 SLES 8 不再支持 64 位的 IBM Developer Kit for Java,所以您需要使用 32 位的 IBM Developer Kit for Java。 通过下面的步骤下载并安装 IBM Developer Kit for Java。

  1. 下载 IBM Developer Kit for Java, 它叫做 SDK。点击页面上右边的 Download。选择 IBM SDK for 32-bit iSeries/pSeries,下载 32 位的 SDK。可能会有多个可用的版本,所以,除非您需要特定的版本,您可能都会希望下载最新的版本。当前最新的版本是 1.4.1 SR2。选择版本后,再选择 Continue,系统会向您询问注册信息。给出这些信息后,您将被重定向到一个 下载页面,类似于图 1 所示。
    图 1. 下载
    下载
    下载

    您既可以以 .tgz 程序包的形式也可以以 .rpm 程序包的形式下载 SDK。安装 SDK 的最简单的方法是下载 .rpm 程序包。 要这样做,请在标识为 SDK 的方框中查找名为 IBMJava2-SDK-ppc-1.4.1-2.0.ppc.rpm 的程序包(取决于您所 选择的版本,这个名称可能是其他类似的名称)。点击程序包名右边的 Accept License

  2. 下载完 .rpm 程序包后,就可以通过运行下面的命令来安装它了,必要时,请用您的程序包名替换掉这里给出的 程序包名:
    # rpm –i IBMJava2-SDK-ppc-1.4.1-2.0.ppc.rpm
  3. 安装完 SDK 后,使用正确的信息设置 PATH 和 JDKDIR 环境变量。下面给出的只是示例, 取决于您的安装的 SDK 的版本,路径可能会不同:
    # export PATH=/opt/IBMJava2-ppc-141/jre/bin:
    /opt/IBMJava2-ppc-141/bin:$PATH
    # export JDKDIR=/opt/IBMJava2-ppc-141

    如果您使用的是老的、得到支持的 64 位 SDK,那么您还需要设置下面的变量:
    # export JAVA64=64

接下来的步骤是修补、编译并引导内核。

修补、编译并引导内核

遵循本节中的步骤来修补、编译并引导 SLES 8 内核,以使得它可以运行 Performance Inspector 工具 所需要的 Performance Inspector 代码。

如果以前没有编译并引导过 SLES 8 内核,那么首先得确保可以使用没有修补的、没有修改的 SLES 8 内核代码 编译并引导一个“后备内核”。那样,如果在使用 Performance Inspector 补丁编译或引导内核遇到问题时,您将可以 知道遇到的问题是 Performance Inspector 补丁引起的还是编译和引导的过程引起的。

遵循下面的说明编译并引导一个后备内核。跳过第 4-8 步说明,因为它们说明的是如何应用 Performance Inspector 补丁。 当做到第 9 步时,建议您运行 make xconfig ,然后在出现的窗口上,直接点击 Save and Exit。忽略第 9 步中关于点击 Performance Inspector 按钮的说明,只有应用了补丁后, Performance Inspector 按钮才会出现在窗口中。除了那些例外之处以外,编译并引导一个后备内核与编译并引导 一个修补过的内核是相同的。

成功地编译并引导了后备内核后,再次执行这些步骤来使用 Performance Inspector 补丁编译内核,不要再忽略任何步骤。

  1. 如果您的系统中没有内核源代码,那么需要从 SLES 8 的原始安装 CD 中安装它。内核源代码的程序包名是 kernel-source。 确保您是从原始 CD 而不是从服务包 CD 安装源代码。Performance Inspector 补丁当前只能用于 2.4.19 内核。服务包 CD 中所包含 的是内核最新版本的内核源代码,不能与此补丁一起使用。图 2 展示的是在 yast2 工具中选择安装的 kernel-source 程序包。
    图 2. Kernel-source 程序包
    Kernel-source 程序包
    Kernel-source 程序包
  2. 您还需要安装一个 64 位交叉编译器(cross-compiler),如果原来没有安装的话。编译 64 位内核需要这个 编译器。您必须以 64 位模式编译内核,因为用于 PowerPC 的 SLES 8 不支持 32 位内核。这个程序包的 名称是 cross-ppc64-gcc。您可以自原始 CD 或服务包 CD 安装这个编译器程序包。

    安装完这个程序包后,确保您的 $PATH 环境变量中有 /opt/cross/bin,以使得在内核编译过程中可以使用这个程序包中的工具。 图 3 展示的是在 yast2 工具中选择安装的 cross-ppc64-gcc 程序包。

    图 3. 选择安装的程序包
    选择安装的程序包
    选择安装的程序包
  3. 确认 /usr/src/linux 链接指向 2.4.19 内核源代码( -l 标记指的是字母 l,而不是数字 1):
    # ls –l /usr/src/linux

    您应该得到类似如下的输出:
    lrwxrwxrwx    1 root     root     17 May 19 09:56 
       /usr/src/linux -> linux-2.4.19.SuSE

    使用下面的命令制作内核源代码树的一个备份拷贝:

    # cp -r /usr/src/linux-2.4.19.SuSE /usr/src/linux-2.4.19.SuSE.bak

    通过内核源代码的一个干净版本来进行编译,以避免出错。如果您以前曾经尝试自 /usr/src/linux 链接当前指向的目录 进行编译,那么将 /usr/src/linux 链接重新指向一个干净的内核源代码目录,比如您的备份目录:

    # rm /usr/src/linux
    # ln -s /usr/src/linux-2.4.19.SuSE.bak /usr/src/linux

    如果您的内核源代码已经经过了修改,而且没有可用的备份目录,那么可以将内核源代码程序包缷载,然后再重新安装。 重新安装后,确认 /usr/src/linux 链接指向您刚刚重新安装的干净的内核源代码树,然后继续后面的步骤。

  4. 确保您处在 /usr/src/linux 目录中,这样您就可以安装内核和驱动程序补丁:
    # cd /usr/src/linux
  5. 安装内核补丁(strip 后面的 1 是数字 1 而不是字母 l):
    # patch --strip 1 -–verbose
    </piperf/patches/ppc64/pi.SuSE.2419.patch  
      	   >/tmp/patch.log
  6. 运行下面的 grep 命令,以确保补丁成功安装。这个命令应该不会返回任何内容:
    # grep –i fail /tmp/patch.log
  7. 安装驱动程序补丁。驱动程序补丁的名称可能会有所改变,所以您可能需要查看 /piperf/patches 目录以 找到最新的 pi.driver 补丁(strip 后面的 1 是数字 1 而不是字母 l):
    # patch --strip 1 --verbose  
    </piperf/patches/pi.driver.2004-04-01.patch
       >/tmp/driver.log
  8. 运行下面的 grep 命令,以确保补丁成功安装。这个命令应该不会返回任何内容:
    # grep –i fail /tmp/driver.log
  9. 您将需要创建一个在内核编译过程中会用到的 .config 文件。要创建一个 .config 文件,首先通过执行 # cd /usr/src/linux 以确保您在 /usr/src/linux 目录中,然后运行 # make xconfig 命令。

    make xconfig 需要 Xwindows。如果您没有在您的 Linux 机器上运行 Xwindows,那么 首先需要将显示输出到一台运行着 Xwindows 的机器上,在那台运行着 Xwindows 的机器上输入 # xhost + 命令。 然后在运行着 Linux 的机器上,输入下面的命令,用运行着 Xwindows 的机器名替换 minotaur.austin.ibm.com:

    # export DISPLAY=minotaur.austin.ibm.com:0.0

    当您运行 make xconfig 命令时,将显示出一个类似于图 4 的窗口。

    图 4. 内核配置
    内核配置
    内核配置

    如果 Performance Inspector 补丁安装正确,那么在这个窗口中应该会有一个 Performance Inspector 按钮。如果没有看到这个按钮,那么确保您已经如前面所展示的那样输入了应用补丁的命令。有时,如果没有 正确输入补丁命令,在日志文件中也不会出现“fail”消息,但是补丁却不会得到应用。如果输入有误,您可以重新 运行补丁命令,然后再次运行 make xconfig 。现在点击 Performance Inspector, 您将看到如图 5 所示的窗口。

    图 5. Performance Inspector
    Performance Inspector
    Performance Inspector

    选择代表模块的 m,然后点击 Main Menu。在原来的窗口中点击 Save and Exit

    当您从 make xconfig 退出后,在 /usr/src/linux 目录中就应该已经为您创建了 一个 .config 文件。可以通过搜索 CONFIG_PERFORMANCE_INSPECTOR=m 行来确认在这个 .config 中已经正确设置 了 Performance Inspector 标记。

    在 Performance Inspector 窗口中您可能选择的是 y而不是 m。选择 y 会将 Performance Inspector 代码直接编译到内核中。推荐您使用 m 以将 Performance Inspector 编译为一个模块。这样会更方便地升级工具程序 包,因为您将不需要再重新编译和重新引导内核。

  10. 现在您将需要编译内核。在 /usr/src/linux 目录中,运行下面的命令:
    # make dep CROSS_COMPILE=powerpc64-linux- SUBARCH=ppc64
    ARCH=ppc64 zImage modules modules_install
  11. 将新内核拷贝到 boot 目录中:
    # cp arch/ppc64/boot/zImage  /boot/piperf.zImage
  12. 将下面的一组配置添加到 /etc/yaboot.conf 文件中以更新引导加载器:
    image=/boot/piperf.zImage 
    label=piperf.zImage
    root=/dev/sda3

    root 域指定的是您想用哪个磁盘分区作为 root 分区。指派给这个域的值取决于您具体的配置,所以上面所展示的值 /dev/sda3 可能 是不对的。您可以运行 # df / 命令来确定指派给 root 域的正确的值。

  13. 使用 # shutdown –r now 重新引导。
  14. 当 yaboot 开始运行时,您可以按下 Tab 键来查看所有可用内核的列表。您的新内核应该会显示在那个列表中。输入您的 内核的名称并按下 Enter。新内核现在将引导起来。

接下来的步骤将是编译 Performance Inspector 工具。

编译 Performance Inspector 工具

如果您希望使用 Performance Inspector Java 工具,那么要确保您已经安装了 Java 并使用正确的信息设置了下面的 PATH 和 JDKDIR 环境变量。如果没有设置这些环境变量,Java 工具将不能被编译。下面给出的只是示例;取决于您所 安装的 SDK 的版本,路径可能会不同:

# export PATH=/opt/IBMJava2-ppc-141/jre/bin:
/opt/IBMJava2-ppc-141/bin:$PATH
# export JDKDIR=/opt/IBMJava2-ppc-141

如果您使用的是老的、得到支持的 64 位 SDK,那么您还需要设置这个变量: # export JAVA64=64

现在需要运行 tinstall 脚本来编译 Performance Inspector 工具:

# cd /piperf/bin
# ./tinstall

配置 Performance Inspector

每次登录后,都需要运行 setrunenv 脚本来配置 Performance Inspector:

# cd /piperf/bin
# . setrunenv

现在 Performance Inspector 工具就可以使用了。后面的章节将解释如何使用它们。

Tprof

Tprof 工具是一个计时器剖析器,可以识别出在用户指定的一个时间间隔内哪些代码在 CPU 上运行。它通常用来 帮助诊断 CPU 使用中的所有热点(hot-spot)。当它运行时,它会记录每次系统时钟中断发生时正在执行的指令 的地址。在大部分系统中,每个处理器每秒钟发生 100 次中断。当用户指定的时间间隔结束时,Tprof 将这些 指令按进程、线程、模块和子例程进行分组。然后,它生成一个报告,列出这些代码单元每个获得了多少个“节拍(tick)” (即当代码的特定单元正在运行时发生了多少次系统时钟中断)。Tprof 为多种类型的代码提供这一信息,包括应用 程序代码、库例程以及内核代码。

Tprof 如何工作?

Tprof 工具实际上是一个名为 run.tprof 的 shell 脚本,它会去运行 swtrace 工具,后者可以自内核中的追踪挂钩收集 追踪数据。当 Tprof 调用 swtrace 时,它会指明需要哪个具体的追踪挂钩。然后,当发生系统时钟中断时,swtrace 工具 会给出正在运行的每一个指令的地址,以及对应于每个指令的进程 id 和线程 id,这样稍后就可以根据进程 id 和线程 id 分配那个节拍。这一信息存储在已经为每个处理器分配的追踪缓冲区中。每个追踪缓冲区默认的大小是 5 MB,不过,当 您运行 Tprof 工具时可以覆盖这一默认值。在用于 Java 代码的 jprof 工具的帮助下,a2n 共享库可以完成地址到符号名的 映射。地址到符号名的映射使得 Tprof 可以按模块和子例程分配节拍。然后由后继的工具生成最终的 Tprof 报告。swtrace、a2n 库、jprof 以及后继工具都是 Performance Inspector 安装的组成部分。

Tprof 是否可以剖析发生特定事件时(除了系统时钟中断以外)什么代码在进行?

Tprof 的一些版本可以记录每次特定事件发生时(比如当缓存失败或运行分支时)什么代码在运行,而不是记录每个 系统时钟中断发生时什么代码在运行。这一特定功能只能用于 x86 体系结构,当前还不能用于 PowerPC。

Tprof 度量的是 CPU 时间还是实际时间?

由于 Tprof 记录在每个系统时钟中断发生时什么代码在 CPU 上运行,所以您可以认为它粗略地度量了代码(比如 进程或子例程)的每个单元所消耗的 CPU 时间数量。它只是列出它运行的时间间隔内所获得的节拍数量总和;它不会 列出这些节拍发生在时间间隔的哪一时刻。当代码禁用中断时,节拍将不能归结到代码,直到中断被重新启用。

如何运行 Tprof?

假定您将 Performance Inspector 工具套件安装在默认的位置,即 /piperf 目录,那么运行 Tprof 的脚本 可以在 /piperf/bin 中找到。可以通过运行 run.tprof [buffer_size] 调用这个脚本。 在 PowerPC 上这个脚本使用一个可选参数 buffer_size,它的单位是 MB。这指明了为每个处理器创建的追踪 缓冲区的大小,追踪缓冲区用于存储 Tprof 运行过程中生成的追踪信息。如果您忽略了这一参数,则 Tprof 将使用默认的缓冲区大小 —— 5 MB。

运行 run.tprof 脚本后,Tprof 将要求您在准备好开始追踪时按下 Enter。这就让您有机会可以启动所有希望包括在 追踪中的程序。按下 Enter 后,Tprof 将开始收集数据,直到您再次按下 Enter 以停止追踪,或者直到追踪缓冲 区变满。当停止追踪后,将在当前工作目录下生成一个名为 Tprof.out 的 Tprof 报告。一个包含运行信息的名 为 run.tprof.log 的日志文件也将创建在同一目录中。

例 1:

# /piperf/bin/run.tprof

例 2:

# /piperf/bin/run.tprof 10

如何解读 Tprof 报告?

Tprof.out 报告包括一个头和 Tprof 报告总结。Tprof.out 文件的头如下:

Tprof Reports
     ProcessorSpeed      1451000000
     TraceCycles         2744696387
     TraceTime           15.123(sec)
TOTAL TICKS            3026
(Clipping Level :      0.0 %    0 Ticks)

ProcessorSpeed 是以 Hertz 为单位给出的处理器速度。TraceCycles 是追踪过程中 CPU 周期的 总数。TOTAL TICKS 是追踪时间间隔过程中发生系统时钟中断的次数。Clipping Level 是报告中 省略的或忽略的节拍所占的最低百分比。省略级别用来限制对应于获得很少节拍的代码 的报告中出现的数据总数。

在下一部分您将看到 Tprof 报告总结。Tprof 收集的数据是每个搜集获得的节拍的数目,不过这些数据可以 以不同的方式来描述。报告总结中的第一部分展示了按进程分配的节拍数目:

================================
  )) Process
================================
LAB     TKS       %%%      NAMES
PID    1612      53.27     SystemProcess_0000
PID     727      24.03     java_06a3
PID     687      22.70     in.telnetd_0438

Process 部分展示了在此时间间隔内运行的每个进程被分配了多少节拍。右边标签为 NAMES 的一栏中 列出了进程的名字。TKS 和 %%% 两栏分别给出了每个进程获得的节拍总数及进程获得的节拍数所占 百分比。LAB 栏指明了这是哪种代码单元类型。LAB 是 LABEL 的简写。在这一部分,所有代码单元都将是 PID 或进程。在后面的部分您将看到的其他类型的代码单元是表示内核线程的 TID,表示模块的 MOD,以 及表示符号(子例程名)的 SYM。

Tprof 报告总结中的其他部分更复杂一些,但也只是对这一主题稍加变化。下面的内容摘录自 Process_Thread_Module_Symbol 部分:

================================
  )) Process_Thread_Module_Symbol
================================
LAB   TKS   %%%     NAMES
PID   1612 53.27    SystemProcess_0000
    TID   1612  53.27     tid_0000
       MOD   1611  53.24      vmlinux
          SYM   1607  53.11       .idled
          SYM      4    0.13      .schedule
       MOD      1   0.03      NoModule
          SYM      1    0.03       NoSymbols

Process_Thread_Module_Symbol 部分列出了 Process 部分的每一个进程。这里摘录的只是第一个进程,因为 将其他进程也列出来将需要好多页!对 SystemProcess_0000 的统计与 Process 部分相同。代码单元的类型是 PID, 节拍数是 1612,占总节拍数的百分比是 53.27。

此部分与 Process 部分的不同之处在于,它将进程代码分为了更小的代码单元。一个进程中运行的代码可以划分为线程, 线程可以划分为模块,模块可以划分为独立的子例程。在上面的数据中,SystemProcess_0000 运行内核线程 tid_0000 中的代码。在以后的发行版本中 Performance Inspector 会支持 Native POSIX Threading Library(NPTL),不过 当前您可以认为 TID 指的是内核线程。

而 tid_0000 线程又会运行两个模块中的代码。线程运行的第一个模块是 vmlinux,或内核代码。内核代码中子例程是 idled (当 CPU 空闲时运行的进程)和 schedule(内核调度器)。为这个进程列出的第二个模块是 NoModule。可以被认为是 NoModule 的代码例子是设备驱动程序或者是在没有 Java profiler 的条件下运行的 Java 代码,在这种情况下 Tprof 将不能完成 从指令地址到模块和子例程名的映射。Tprof 报告总结中的其他部分与此类似,所以只要您理解了这一部分,解读报告的 其他部分就很直观了。

Above idle(AI)

AI 工具显示在用户指定的一段时间间隔内的 CPU 使用率统计数据。它显示三方面统计数据来描述 CPU 的利用率:

  • CPU 空闲所占的时间百分比。
  • CPU 繁忙所占的时间百分比。
  • CPU 处理中断所占的时间百分比。

如果您有多个 CPU,它将给出每个 CPU 的统计数据以及系统中所有 CPU 的平均统计数据。

AI 命令实际上是 swtrace 所提供的一个专门功能,后者是安装为 Performance Inspector 工具套件的一部分的软件 追踪工具。在被请求的时间间隔内,swtrace 将执行一个对 Performance Inspector 设备驱动程序的 ioctl( ) 调用来获取空闲信息。

CPU 繁忙所占的时间百分比是否包括 CPU 处理中断所占的时间百分比?

不包括。CPU 处理中断所占的时间百分比并不是那个 CPU 全部繁忙时间的子集。AI 生成的三方面的统计数据指的是 三块独立的时间。

如何运行 AI?

假定您将 Performance Inspector 工具套件安装在默认的位置,即 /piperf 目录,那么可以在 /piperf/bin 目录下找 到 AI 工具。可以通过执行下面的命令来运行 AI 工具:

swtrace ai [sample_interval [num_samples]]

sample_interval 和 num_samples 参数是可选的。sample_interval 参数的单位是秒,指定的是每隔多长 时间对 CPU 的利用率进行抽样和显示。num_samples 间隔指定了应该执行多少次抽样。如果 sample_interval 参数 被忽略,则使用默认抽样时间间隔,1 秒。如果 num_samples 参数被忽略,则抽样将一直进行,直到您按下 Ctrl-c 或 Ctrl-Break。

例 1:

# /piperf/bin/swtrace ai

例 2:

# /piperf/bin/swtrace ai 5

例 3:

# /piperf/bin/swtrace ai 2 3

如何解读 AI 命令的输出?

在一个有 2 个 CPU 的系统中,会得到类似如下的输出:

Percentage by processor:
   CPU 0  IDLE=  0.00, BUSY=100.00, INTR=  0.00
   CPU 1  IDLE=  0.00, BUSY=100.00, INTR=  0.00
Percentage by System:
          IDLE=  0.00, BUSY=100.00, INTR=  0.00

“Percentage by processor” 列出了系统中每个 CPU 的统计数据。为每个 CPU 显示出了 CPU 空闲所占的时间百分比、CPU 繁忙所占的时间百分比以及 CPU 用来处理中断所占的时间百分比。“Percentage by System”列出了同样的统计, 不过不是将它们按一个 CPU 一个 CPU 来显示,而是显示所有 CPU 系统整体平均统计数据。

PTT

PTT 工具收集在用户指定时间间隔内运行的所有进程的统计数据。到目前为止,PTT 尚不支持 Native POSIX Threading Library(NPTL),所以线程这一术语与进程是同义的。PTT 收集每个进程的以下统计数据:

  • 进程名。
  • 进程 id。
  • 进程所使用的 CPU 周期数目。
  • 进程所使用的 CPU 周期数目占总数目的百分比。
  • 进程运行时发生的中断的数目。
  • 进程被调度的次数(或者说是内核调度子例程为那个进程释放 CPU 的次数)。

可以通过一个名为 run.ptt 的脚本来调用 PTT 工具。这个脚本调用命令行工具 ptt 和 pttstat 来收集所 需要的统计数据。

PTT API 是怎样的?

除了命令行工具 ptt 和 pttstat 以及调用它们的 run.ptt 脚本以外,还有一组您可以用来装备您的 Java 和 C 应用 程序的 PTT API。当前,这些 API 可以为 PowerPC 给出在被装备的程序中两个成功的 API 调用之间所发生 的基于时间的节拍数目。参阅 Linux Per Thread Time APIs 以获得关于如何实现 PTT API 的资料。

如何运行 PTT?

假定您将 Performance Inspector 工具套件安装在默认的位置,即 /piperf 目录,那么可以在 /piperf/bin 目录中 找到 PTT 工具。可以运行 run.ptt 脚本来调用 PTT 工具。这个脚本不使用任何参数。当您运行这个脚本时,工具立即 开始收集统计数据。当您希望停止收集数据时,按下 Enter,然后就会生成一个报告。例如,

/piperf/bin/run.ptt

如何理解 PTT 的输出?

按下 Enter 键后,您将看到类似如下的统计数据:

ptt version 2040024
* Opening ptt.out For ptt Output
total cycles     1,461,557,204
DISP    IRQ          Cycles        %       PID     PNM
410      4     1,459,143,201     99.8        0     IDLE
403      0         2,256,862      0.2       15     khvcd
  2      1           126,544      0.0     9227     bash
  4      0            19,189      0.0     8197     in.telnetd
  1      0             4,654      0.0       10     kupdated
  1      0             3,649      0.0        1     init
  2      0             2,593      0.0      774     nscd
  1      0               512      0.0       18     kreiserfsd

可以直观理解这些统计数据。在顶部“total cycles”行中显示的是 PTT 工具所收集的在此时间间隔内的 CPU 周期总数; 下面的图表列出了此时间间隔内运行的所有进程以及每个进程的总计的统计数据。在右边标签为 PNM 的一栏中是进程的 名称。进程的 id 在其左边的标签为 PID 的栏中。左边紧接着是 Cycles 和 % 栏。Cycles 栏中的数字列出了在 PTT 收集 统计数据的时间间隔内那个进程所使用的 CPU 周期数。% 栏显示了进程所使用的 CPU 周期所占总周期数的百分比,当然 是用 Cycles 栏的数目除以图表上方“total cycles”的数目而得到的。IRQ 栏指明了在进程进行过程中发生的中断的数目。 最后,DISP 栏指明了在 PTT 工具收集统计数据的时间间隔内进程被调度的次数。

JLM

JLM 工具提供 Java 程序中对锁的统计数据。这些统计数据包括锁被请求的方式、锁被持有的总时间以及锁被持有的平均时间。 它可以与 IBM 32 位和 64 位的 Runtime Environment for Linux v1.4.0 和更新的版本一起使用。JLM 工具不能与非 IBM JVM 一起使用,因为这个工具使用了 IBM 对 JVM Profiler Interface(JVMPI)的扩展。

JLM 是 Java 剖析器所提供的一个专门功能,后者通常称作 jprof。Java 剖析器在 PowerPC 上实现为 libjprof.so 库。 基于套接字的命令行应用程序 rtdriver 提供了访问 Java 剖析器的接口。类似于其他 Performance Inspector 工具, 可以在 /piperf/bin 目录中找到 rtdriver 和 libjprof.so。

如何运行 JLM?

  1. 首先需要运行您的 Java 程序。需要使用 Xrunjprof:socket 标记来启动 Java 剖析器。例如,如果您的 Java 类命名为 MyJava,则执行命令:
    # java –Xrunjprof:socket MyJava
  2. 运行 rtdriver 应用程序(传递给下面的命令的 -l 标记是小写字母 l,不是数字 1):
    # rtdriver –l
  3. 当 rtdriver 应用程序连接到本地主机后,它将显示一个 Command> 提示符。在提示符中输入下面的 命令来通知 Java 剖析器开始收集锁统计数据:
    Command> jlmstart
  4. Java 剖析器可以在任何时刻生成关于当前锁统计数据的报告。另外,您还可以在同一个 rtdriver 会话中生成多个报告。 每个报告都将存储在当前工作目录中的 log_jlm.#_pppp 文件中,其中的 # 是报告的序列号,从 1 开始是 第一个报告,然后接下来每个报告增 1, pppp 指的是进程的 id。在 Command> 提示符中输入下面的命令以生成一个 报告:
    Command> jlmdump
  5. 当您停止收集锁统计数据时,在 Command> 提示符中输入下面的命令:
    Command> jlmstop
  6. 在 Command> 提示符中输入下面的命令以退出 rtdriver:
    Command> quit

如何解读 JLM 报告?

下面的内容摘录自一个 log-jlm 文件:

Java Lock Monitor Report
Version_5.0
Built : (Tue Apr 27 13:57:19 PDT 2004)
Platform : (Linux-ppc64)
JLM_Interval_Time 26896040
System (Registered) Monitors
%MISS GETS NONREC SLOW REC TIER2 TIER3 %UTIL AVER-HTM MON-NAME
 0     4     2     0    2    0     0     0   26898   Monitor Cache lock
 0     2     2     0    0    0     0     1   151640  Thread queue lock

报告包括三个部分,一个头,随后是两部分:System(Registered)Monitors 和 Java(Inflated)Monitors。 System(Registered)Monitors 中的锁由 JVM 及其组件持有,Java(Inflated)Monitors 中的锁由用户 Java 程序 持有。为简短起见,前面的摘录中略去了 Java(Inflated)Monitors 部分,不过,Java(Inflated)Monitors 中的锁的 统计数据解释与 System(Registered)Monitors 部分所展示的锁完全相同。

头中包含的是关于 JLM 工具的信息,包括运行的工具的版本,工具是何时编译的,以及工具所运行的平台。 JLM_Interval_Time 域中包含的是自执行 jlmstart 命令到执行 jlmdump 命令期间所发生的时基节拍数。

接下来,报告显示了 System(Registered)Monitors 的统计数据。需要对这些统计数据做一下关于锁被请求的方式 的简短说明。可以通过两种方式( 递归地非递归地)的其中一种来请求锁。如果锁是以递归方式被请求, 那么发出请求的线程已经持有了它。如果锁是以非递归方式被请求,则发出请求的线程还没有持有它。有两种类型的 非递归锁:快的和慢的。快锁是立即被请求的,没有等待。慢锁由另一个线程持有,在可以被请求之前必须被那另 一个线程释放掉。

System(Registered)Monitors 图表中的统计数据可以如下解释。图表中的每一行指的是一个不同的锁。锁的名称 可以在右侧的 MON-NAME 栏中找到。

意义
%MISS锁以非递归方式被请求但是不得不等待的次数百分比。计算公式为 %MISS = 100 * (SLOW / NONREC)
GETS锁被请求的次数。计算公式为 GETS = FAST + SLOW + REC
NONREC锁以非递归方式被请求的次数
SLOW锁以非递归方式被请求但是不得不等待的次数
REC锁以递归方式被请求的次数
TIER2 and TIER3由于这一信息不用于 PowerPC,所以可以忽略它
%UTIL从执行 jlmstart 命令到执行 jlmdump 命令 期间锁被持有时间所占的百分比。计算公式为 100 * (Hold_Time / JLM_Interval_Time), 其中 Hold_Time是锁被持有时发生的时基节拍数目
AVER-HTM在每一次非递归请求期间锁被持有时发生的平均时基节拍数目

Heap dump

heap dump 工具提供关于在 Java 堆中找到的对象的统计数据,包括每个类的对象数目,分配给每个类的对象的字节数,以及 每个类的对象的平均大小(字节数)。另外的统计数据包括 Java 堆的总的大小,以及 Java 堆的起始和结束地址。heap dump 工具可以 与 IBM 的 32 位和 64 位 Runtime Environment for Linux v1.4.0 或更新的版本一起使用,应该也可以与其他 非 IBM JVM 一起使用,因为它使用的是标准的 JVM Profiler Interface(JVMPI)事件。

类似于 JLM,heap dump 也是 Java 剖析器所提供的一个专门功能。rtdriver 应用程序是 Java 剖析器的一个接口。通过 rtdriver 接口,在任何时刻都可以请求生成 heap dump 报告。可以在 /piperf/bin 目录中找到 rtdriver 应用程序和 在 PowerPC 上被实现为 libjprof.so 的 Java 剖析器。

如何运行 heap dump?

  1. 需要运行您的 Java 程序。需要使用 Xrunjprof:socket,classloadinfo 标记来启动 Java 剖析器。例如, 如果您的 Java 类被命名为 MyJava,那么运行下面的命令:
    # java –Xrunjprof:socket,classloadinfo MyJava
  2. 运行 rtdriver 应用程序(传递给下面的命令的 -l 标记是小写字母 l,不是数字 1):
    # rtdriver –l
  3. 当 rtdriver 应用程序连接到本地主机后,它将显示一个 Command> 提示符。您可以在任何时刻 请求一个关于当前 Java 堆使用情况的报告。在同一个 rtdriver 会话中您也可以生成多个报告。 每个 heap dump 报告实际上包括一组两个文件,存储在当前工作目录中,名为 log_hd.#_pppp 和 log.hdcnm.#_pppp,其中 # 是报告的序列号,从 1 开始是第一个报告,然后接下来每个 报告增 1, pppp 指的是进程的 id。在 Command> 提示符中输入下面的命令来生成一个报告:
    Command> heapdump=1
  4. 要退出 rtdriver,在 Command> 提示符中输入下面的命令:
    Command> quit

如何解读 heap dump 报告?

heap dump 报告包括两个文件,一个 log-hd 文件和一个 log-hdcnm 文件。首先查看 log-hd 文件。 其内容类似如下:

 # HEAPDUMP
 # level             1
 # begin             0x8004ea3090
 # end               0x8004ed11db
 # num_traces        5
 # traces            0x7fe05e0cc0
 # HEAPDUMP SIZE  =  188747

HEAPDUMP SIZE 标签指明的是 Java 堆的总的大小,在本例中是 188747 个字节,以 10 进制格式给出。 Java 堆的范围是从“begin”标签指明的内存地址到“end”标签指明的内存地址。在本例中,堆的范围 是从 0x8004ea3090 到 0x8004ed11db。

现在来查看 log-hdcnm 文件。这里是一段摘录:

MaxObjectSize : 19088
  
OBJS    BYTES     AVER      %
4765 -539437512 -113208.0  100.0
OBJS    BYTES     AVER     %    CLASS
====    =====    =====  =====   =====
1331   128512     96.0   -0.0   CHAR[]
  24    42160   1756.0   -0.0   BYTE[]
1115    35680     32.0   -0.0   java/lang/String

首先您将会看到 MaxObjectSize 域,它指的是在 Java 堆中找到的最大对象的大小(单位是字节)。然后是描述 在 Java 堆中找到的所有对象的统计数据。首先给出堆中所有对象的一个总结,然后分别是各个类的统计数据。 例如,考虑 CHAR[] 类。在堆中有 CHAR[] 类的 1331 个对象。分配给那些 CHAR[] 对象的总的字节数是 128512, 平均到每个 CHAR[] 对象是 96 个字节。% 栏中的数字指明了 CHAR[] 对象正在使用的空间占总的 Java 堆空间的 百分比。其他每个类的统计数据也可以以同样的方式进行解读。


相关主题

  • 您可以参阅本文在 developerWorks 全球站点上的 英文原文.
  • Performance Inspector 是获得资料的最好来源。它提供用于多种平台的 Performance Inspector 程序包下载,并且有详细的安装与使用说明。
  • SUSE Linux Enterprise Server 8 给出了概述、产品和解决方案列表以及服务的描述。
  • 访问 Tprof 以获得关于此工具的更多资料。
  • 访问 AI 以获得关于此工具和 swtrace 的更多资料。
  • 阅读更多关于 PTT工具的资料。
  • JLM是关于此工具的资料仓库。
  • 访问 JPROF以深入学习 heap dump。

评论

添加或订阅评论,请先登录注册

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Linux
ArticleID=163136
ArticleTitle=用于 PowerPC 上的 Linux 的五个易用的性能分析工具
publish-date=07202004