技术开发 频道

使用VPA快速洞悉Java应用性能瓶颈

  【IT168 技术】

  引言

  类是 Java 的基础。大规模的 Java 应用是由成千上万个类构成的。当出现性能问题时,如何才能在这一大堆类中迅速定位性能瓶颈呢?更糟糕的是,有些类是由某个同事在上个世纪编写的,某些类是第三方提供的,没有人明白这些类给整个应用带来了怎样的性能影响。

  VPA 中的两个工具:Profile Analyzer 和 CallTree Analyzer,对 Java 应用程序的性能分析提供了有力的支持。这两个工具提供了多个视图,帮助用户从不同的角度分析性能数据。通过这两个工具帮助,用户可以快速地从这成千上万行的代码中找到性能最差的方法或者代码行。

  使用 VPA 分析性能问题的过程可以分为三步:

  针对不同性能问题,选择恰当的性能分析工具;

  采集性能数据;

  使用 VPA 分析性能数据;

  本文将以小程序 bookstore 为例,介绍如何使用这两个工具快速定位性能问题。

  小程序 bookstore

  bookstore 是个基于 AWT 的图形界面程序。它读取图书索引文件到内存中,然后列出文件中包含的所有图书分类。如果用户在分类列表中选中某个图书分类,图书列表中会列出所有该分类下的图书。图 1 是小程序 bookstore 图形界面的截图。


▲图1 bookstore 小程序

  bookstore 小程序有两点性能问题:

  打开比较大的图书索引文件需要比较长的等待时间。

  如果用户选中一个分类,bookstore 小程序会很长时间不响应,并且 100% 地占用 CPU 资源。

  选择恰当的性能分析工具

  Java 应用的性能问题多种多样,有 IO 方面的,也有处理器资源方面的。针对不同的性能问题,性能分析师需要使用不同的采样手段和分析工具。VPA 中有两个工具可以用于分析 Java 应用的性能问题:Profile Analyzer 和 Call Tree Analyzer。它们适用于不同的性能问题。

  Call Tree Analyzer 可以帮助用户找到耗时最长的方法以及该方法的所有调用堆栈,对所有与速度相关的性能问题都适用。

  Profile Analyzer 则对于那些和处理器资源密切相关的性能问题(比如 CPU 利用率 100%)有比较强的针对性。

  Profile Analyzer

  Profile Analyzer 被用于分析抽样数据。抽样采样时,系统每隔一定周期,采样一次,采集当前正在运行的指令的地址、线程号和进程号。根据被抽样到的概率不同,可以知道哪些进程、线程、指令消耗了最多的处理器资源。除此之外 , 抽样采样给应用造成的额外开销比较小。Profile Analyzer 为抽样采样数据的分析提供了一系列的文字或者图形的视图。通过这些视图,分析师可以将性能瓶颈定位到进程、线程、类、方法甚至具体的代码。

  小程序 booksotre 的第二个性能问题是 CPU 资源相关的性能问题,通过 Profile Analyzer 可以迅速找到占用处理器资源最多的代码。

  Call Tree Analyzer

  Call Tree Analyzer 被用于分析方法调用追踪数据。方法调用追踪数据中记录了方法调用堆栈和方法调用的起始时间。方法调用追踪数据可以用于分析各种速度相关的性能问题。Call Tree Analyzer 将方法调用追踪数据以方法调用树的形式展现出来。通过对方法调用树的分析,用户不仅可以找到自身调用时间最长、总调用时间最长的方法,还可以根据这些方法的调用堆栈了解到性能瓶颈形成的原因。

  小程序 bookstore 的第一个性能问题有可能是 IO 问题,Profile Analyzer 不适用于这样的问题,可以用 Call Tree Analyzer 来寻找性能瓶颈。

  性能采样

  VPA 支持多种不同格式的性能数据。表 1 中列出了 VPA 支持的 VPA 支持的性能数据格式。这里以小程序"bookstore"为例,介绍如何通过 Performance Inspector 采集抽样数据和方法调用树。


▲表 1. VPA 支持的性能数据格式

  配置环境变量

  使用 Performance Inspector 采集性能数据,首先需要告诉采样工具相关的环境变量。

  清单 1. 设置环境变量

> cd /d c:\ibmperf\bin
> setrunenv

  采集抽样结果

  TPROF 是 Performance Inspector 提供的抽样采样工具。TPROF 允许用户只采集某一段时间的抽样。使用 TPROF 对 bookstore 小程序采样时,

  首先启动 TPROF,如清单 2,执行"run.tprof"命令

  清单 2. 启动 TPROF

> cd /d c:\ibmperf\bin
> setrunenv
> run.tprof

  然后,如清单 3,打开另外一个命令行窗口,执行命令 java -Xjit:enableJVMPILineNumbers -Xrunjprof:tprof,fnm=C:\ibmperf\bin\log,pidx-jar bookstore.jar,启动 bookstore 小程序。

  清单 3. runjprof:tprof

> cd /d c:\ibmperf\bin
> setrunenv
> java -Xjit:enableJVMPILineNumbers \
      
-Xrunjprof:tprof,fnm=C:\ibmperf\bin\log,pidx \
      
-jar bookstore.jar

  打开图书索引文件。

  选中图书分类的第一项后,立即在 TPROF 的命令行窗口中敲下回车键。TPROF 开始采样。

  小程序恢复响应并显示图书列表后,在 TPROF 的命令行窗口中敲下回车键。TPROF 结束采样。

  采样结束后,执行命令"mergetprof",将代码行等信息合并到抽样采样数据中。

  在 Performance Inspector 安装目录的 bin 文件夹下生成了"tprof_e.out”文件。这个文件就是可以被 Profile Analyzer 读取的抽样采样数据。

  采集方法调用树

  JPROF 是 Performance Inspector 中的一个工具,可以通过 JVMTI 或 JVMPI 接口纪录方法的调用信息。对 bookstore 采集方法信息时,

  首先,如清单 4 执行,命令 java -Xrunjprof:callflow,raw_cycles,start-jar bookstore, 启动 bookstore。

  清单 4. runjprof:calltree

> cd /d c:\ibmperf\bin
> setrunenv
> java -Xrunjprof:callflow,raw_cycles,start -jar bookstore.jar

  然后,打开图书索引文件。

  文件读取结束后,关闭 bookstore 小程序。

  在当前目录生成了一个 log-rt.xxx文件。将这个文件重命名为 log-rt.xxx.jprof,Call Tree Analyzer 就可以打开这个 Call Tree 文件。

  分析采样结果

  使用 VPA 打开采样数据文件,VPA 会根据性能数据的文件类型,自动打开相应的性能分析工具。VPA 提供了大量图型的和文字的视图,帮助用户从不同角度分析性能采样。

  分析抽样结果

  使用 Profile Analyzer 分析 Java 程序的性能问题时,编辑器、Source Code 视图和 Java Hierarchy 视图是比较常用的控件。

编辑器可以帮助用户找到 Ticks 最多的方法。如图 2,tprof_e.out 打开后,编辑器按照"Process > Module"或者"Process > Thread >Module"等不同分层模式以树状结构列出了采样到的进程、线程和模块。JITCODE 模块是 Java 进程中 Ticks 最多的模块,而 BestAuthor$1.valueChanged 方法是 JITCODE 模块中 Ticks 最多的方法。


▲图2 Profile Analyzer 的编辑器

  Source Code 视图可以帮助用户找到 Ticks 最多的代码行。在编辑器中双击方法 BestAuthor$1.valueChanged,VPA 会弹出对话框询问这个方法相应的源文件。如图 3,为方法 BestAuthor$1.valueChanged 指定源文件后,通过 Source Code 视图,可以找到 Ticks 最多的代码行。这样的代码行很有可能是程序的性能瓶颈。


▲图3 Source Code 视图

  通过"Java Hierarchy"视图,用户可以按照 Java 方法所属的包和类逐层浏览这些被采集到的 Java 方法。如图 4,Java Hierarchy 视图的右侧表格中列出了包 bookstore.ui 下所有被采样到的方法。


▲图4 Java Hierarchy 视图

  分析方法调用树

  Call Tree Analyzer 提供了编辑器、Method Overview 视图、Call Stack 视图等控件。

  如图 5,编辑器以方法调用树和执行图的方式来展现 JProf 文件。


▲图5 方法调用树和执行图

  "Method Overview"视图列出了方法调用树中所有的方法。如图 6,点击 RAW_CYCLES 列,"Method Overview"按照方法自身消耗时间长短对方法列表进行排序。方法自身消耗时间很长的方法很有可能是性能瓶颈。


▲图6 Method Overview 视图

  在"Method Overview"视图中,双击 BookReader.startElement 方法,Call Stack 视图会显示 BookReader.startElement 方法的调用堆栈。通过图 7 中的调用堆栈,用户可以了解到 BookReader.startElement 方法是怎样被调用的。


▲图7 Call Stack 视图

  在"Call Stack"视图中,双击 BookReader.startElement 方法,可以在 Call Tree 中定位到这个方法。如图 8,用户通过浏览 Call Tree,可以更清楚地了解 BookReader.startElement 方法的上下文。


▲图8 在 Call Tree 中定位BookReader.startElement 方法

0
相关文章