使用 TPTP 对 Eclipse 插件进行性能剖析和调优

Comments

TPTP 及其各子项目简介

TPTP(Eclipse Test & Performance Tools Platform) 是 Eclipse 基金会下的一个开源子项目,提供了一组基于 Eclipse 的工具,对软件开发的各个阶段提供支持。基本已经覆盖了从测试到运行时性能分析、运行状态、日志分析的全过程。从其项目首页来看,其主要开发者来自包括 IBM 和 Intel 在内的大公司。更重要的是,由于其开放性,使得基于其上来开发自己的工具变得非常容易,这样一来就极大地降低了开发 “软件开发辅助工具”的门槛。

TPTP 项目中包含如下几个子项目提供对软件开发各个阶段的支持:

  • Platform

    TPTP 把其基础架构专门做成了一个单独的子项目,也由此可见 TPTP 的意义不仅仅在于它提供了一些用于辅助软件开发的工具,而是致力于提供一个平台,以便更多的软件开发辅助工具可以基于它来进行构建。其实事实亦如此,市面上不少商业测试工具都是基于 TPTP 进行开发的。

    该项目提供了 TPTP 中通用的数据结构、界面显示元素、数据收集和通讯控制机制。它提供了一系列扩展点以便下游项目可以很方便地扩展和重用这些功能。

  • Testing tools

    作为一个用于构建测试工具的基础框架,该子项目提供了一组测试工具通用的特性。例如用于实施测试、准备执行环境以及测试结果的报告和分析。除此之外,该项目还作为对这个基础架构的示例,提供了一个基于 JUnit 的组件测试工具、一个 WEB 性能测试工具以及一个手工测试工具。

  • Tracing and Profiling Tools

    该项目主要解决软件运行时状态分析。其重点就是数据的收集和分析报告。基于 Java 的 JVMPI 监控代理,它不仅可以对本地运行的程序进行分析,同时也可以对运行在不同 JVM 甚至是不同机器上的应用进行监控和分析。

  • Monitoring Tools

    按应用开发生命周期来看,该项目负责的是比较靠后的部分了,它主要负责应用运行时期的监控以及日志分析。通过这个工具 ( 或基于该基础架构构建的工具 ) 可以对应用运行时的各项系统资源进行监控。并且通过其日志分析功能对应用运行时的日志进行在线分析以达到对应用运行时的状态进行监控的目的。

可以看到,TPTP 及其各个子项目已经基本涵盖了应用程序开发过程的各个阶段。而作为软件开发人员,我们更关注的是如何使用 TPTP 来对我们开发的应用进行全面的分析,特别是性能分析以找到性能瓶颈以便对应用进行进一步的优化。所以从软件开发人员的角度来讲,Tracing and Profiling Tools 应该是最有用的工具了。

TPTP 的安装

作为一组 Eclipse 插件,TPTP 的安装与其他插件的安装是非常类似的。下面详细介绍其安装步骤以及安装过程中的一些注意事项。

下载软件

TPTP 目前提供基于 Windows 和 Linux 两个平台的下载,在本文写作时的最新版本是 4.6.1,支持 Eclipse 的最新版本 3.5.1。需要注意的是,TPTP 的版本与 Eclipse 的版本有比较严格的对应关系。你需要根据你使用的 Eclipse 下载对应版本的 TPTP。另外,TPTP 还对其他组件有些依赖,在下载前请保证你的 Eclipse 环境已经满足了 TPTP 的要求。

另外,可选择下载包含所有子项目的完整的 TPTP 软件包,并且也可以选择下载单独的软件包。

根据前文的描述,“platform”子项目为其他全部项目的基础,如果选择单独下载所需要的软件包,请不要忘记同时要下载安装 Platform 包。

下载分 Runtime 和 SDK 两种。如果你不想基于框架继续扩充开发自己的工具,则可以只下载 Runtime 包。

具体的下载要求和地址可参见其产品下载页面:

http://www.eclipse.org/tptp/home/downloads/

同时,在该页面中还有 Agent Controller 的下载,该组件使你可以使用 TPTP 对不同机器上的应用系统进行实时监控。如果被监控的应用跟 TPTP 在同一个系统中,则可以不用单独安装这个组件。

另外,也可以通过 Eclipse 的 Update Manager 安装 TPTP,具体做法可参考:

http://www.eclipse.org/tptp/home/downloads/updateManager.php

但是 TPTP 文件比较大,笔者建议还是先把文件下载下来再自己安装,这样可以使安装过程更快一点。

安装软件

通过 Update Manager 安装的方式可以参考上面给出的地址,里面有详细的介绍。这里我来介绍通过下载文件进行安装的方法。以下的步骤以下载完整 TPTP 组件包为例。

  • 将下载到的压缩包解压缩至 Eclipse 的安装目录

    注意,解压缩后,压缩包里的 plugins 与 features 目录中的内容应该放入 Eclipse 安装目录中的相应目录中。

    或者通过其他方式安装插件,请参考“Manage your Eclipse environment”(http://www.ibm.com/developerworks/opensource/library/os-ecl-manage/)

  • 用 clean 参数启动 Eclipse

    启动 Eclipse 并加入 -clean 参数以清除之前的插件缓存

  • 验证 TPTP 的 Tracing and Profiling Tools 已经正确安装

    当 eclipse 启动后,如果可以打开“Profiling Monitor” view, 则说明 TPTP 以及 Tracing and Profiling Tools 已经正确安装好了。

    图 1. 验证 TPTP 的安装
    图 1. 验证 TPTP 的安装

使用 Tracing and Profiling Tools

我们有这样一个插件,用来从磁盘上读取记录产品信息的 XML 文件,然后在一个表格中将其显示出来。这整个插件最后的表现形式就是一个 Eclipse 视图:

图 2. 应用示例
图 2. 应用示例
图 2. 应用示例

我们的任务就是对这个插件的工作进行性能分析与调优。

以 profile 模式运行应用

对我们的插件进行性能分析,就要先以 profile 模式将其运行起来。MyShop 插件的源代码可以在本文的附件中找到。

图 3. 以 Profile 模式运行应用
图 3. 以 Profile 模式运行应用
图 3. 以 Profile 模式运行应用

插件安装成功后,就可以在工具栏上看到以 profile 模式运行的图标。点击该图标并选择以 Eclipse 应用的方式运行该程序。

接下来是运行配置界面,可以在这里进行运行方式、分析规则等配置。

图 4. Profile 模式下的运行配置
图 4. Profile 模式下的运行配置
图 4. Profile 模式下的运行配置

可以看到,这个运行配置窗口与普通运行窗口的不同就是多了一个 Monitor 标签。在这里可以设置我们要分析的方式和添加分析时的过滤器以便将我们并不关心的类的运行情况从分析报告中过滤掉。

在分析方式上,因为我们要对性能,即程序运行的时间进行分析,所以如上图所示,我们选择使用“Execution Time Analysis”分析方式。

接着选择“Edit Options”对运行参数进行设置:

图 5. 编辑 Profile 选项
图 5. 编辑 Profile 选项
图 5. 编辑 Profile 选项

在我们的配置中,选择图形化的数据类型以便以更直观的方式观察执行过程。但是需要注意的是,选择图形化的数据类型需要耗费较大的系统资源,如果你正在监控的应用比较大则不适合用这个选项,否则可能导致整个程序反应过慢。

接下来设置监控代码的过滤器。

回到运行配置窗口,在 Java Profiling 节点上双击鼠标或选择 “Edit Options”, 进入过滤器设置界面。

可以看到,已经预设好的两个过滤器可以将一些系统的包排除在外。这里我们来新建一个自己的过滤器。

图 6. 过滤器设置
图 6. 过滤器设置
图 6. 过滤器设置

点击上面的 “Add” 按钮增加一个新的过滤器,取名为 MyShop。点击下面的“Add” 按钮增加过滤规则。过滤器支持通配符。上图中我们的过滤器规则为分析 以“net.faquir” 开头的 包中的所有方法并忽略其他任何代码中的任何方法。

点击 “Next” 按钮进行下一步配置。因为我们需要进行性能分析的程序是 Eclipse 插件程序,在我们的视图被调用之前进行分析数据的收集是没有任何意义的。所以我们可以取消“在程序启动时自动开始监控”的选项以便到执行我们需要进行性能分析的时候再打开这个数据收集选项以排除不必要的干扰数据。

图 7. 设置启动选项
图 7. 设置启动选项
图 7. 设置启动选项

完成之后选择“Finish”回到主配置窗口,然后按“OK”以执行程序。

可以看到,此阶段监控服务的状态是暂停的:

图 8. 监视器运行状态
图 8. 监视器运行状态
图 8. 监视器运行状态

收集运行时数据

当主程序完全运行起来后,选择我们的 MyShop 视图并将其调用起来。在我们做下一步操作前,点击 “开始”按钮 ( 参见图 8) 以开启监视器的数据收集。

可以看到,此时 Profilling Monitor 视图中的运行状态已由暂停改为运行 :

图 9. 开始数据收集
图 9. 开始数据收集
图 9. 开始数据收集

接着,进行我们的操作。选择 “browse” 按钮并选择存放我们产品信息文件的目录。产品信息文件可在本文附件中找到。点击 OK 后,可以看到,如图 2 所示,产品信息已经从文件中获取出来了。

操作完成后,我们也获得了我们需要的数据,可以将需要分析的程序关闭,回到前面的 Profilling Monitor 视图中进行具体的数据分析工作。

分析程序调用关系

使用 TPTP 对运行时数据进行分析,其中一个非常有用的功能就是根据运行时数据分析对象之间的调用关系。TPTP 提供 UML 序列图的查看方式。这种方式的分析对刚接手一个不熟悉的程序开发时尤其有用。

回到我们的例子中,当分析程序运行后,就会在 Profilling Monitor 视图中生成相应的报告。如图所示,选择以 UML2 Class Interactions 的方式打开分析报告。

图 10. 以 UML2 Class Interactions 的方式打开分析报告
图 10. 以 UML2 Class Interactions 的方式打开分析报告
图 10. 以 UML2 Class Interactions 的方式打开分析报告

在 UML 序列图的分析中,不仅可以看到类之间的调用关系,其调用过程中的性能瓶颈也会被标记出来。

图 11. 以 UML 序列图展示类之间调用关系
图 11. 以 UML 序列图展示类之间调用关系
图 11. 以 UML 序列图展示类之间调用关系

分析性能瓶颈

可以使用 Execution Statistics 视图来分析程序中各个方法的运行时间。打开该视图的方式是,数据收集进程上点右键,选择以 Execution Statistics 方式打开。

在该视图中,显示了所有调用到的方法及其运行时间。运行时间有多种表示方法。最常用到的就是“cumulative time”。该时间表示了这个方法调用的总耗时,其中包含其调用其他方法的时间。

图 12. 运行统计视图
图 12. 运行统计视图
图 12. 运行统计视图

我们 MyShop 插件的运行结果如上图所示。可以看到,getProductDir 方法耗时最长。而该方法的作用是打开一个文件选择对话框,等待用户的选择,等选择完成后再关闭对话框。因此其时中包含了等待用户选择的部分。这当然应该在我们的性能分析中排除在外。除此之外耗费时间最长的是 parseContent 方法。该方法用于从包含产品信息的 XML 文件中获取真正的产品信息数据。双击该方法查看该方法调用的详细数据。

图 13. 方法调用详细数据
图 13. 方法调用详细数据
图 13. 方法调用详细数据

需要注意的是,在下面的 Selected method invokes 表格中,显示结果是通过我们设置的过滤器过滤后的结果。在上面的结果中,我们可以看到,我们自己的方法调用花费的时间都很小。由此可见,消耗时间更多的地方是在 XML 解析的方法中。

解决性能问题并验证修改

通过对上面运行数据的分析,我们的结论是,对性能影响最大的是 XML 的解析。而根据得到的数据,24 条商品数据的获取就已经需要 0.5s 的时间,而在正常使用中的商品数量则会达到根本不可忍受的程度。通过对代码的分析,我们得知目前的 XML 解析使用的是 DOM 的分析方

式,而在我们的应用中只有 XML 的读操作而没有写操作。在这种方式下,SAX 的解析方式效率要更高。因此我们可以将 XML 解析部分的代码改为 SAX 方式。

  • 创建 ProductSAXParser 类
创建该类实现我们的 ProductParser 接口并继承自 DefaultHandler 接口完成大部分的分析逻辑。
  • 实现 Parser 方法
实现 ProductParser 接口和 DefaultHandler 定义的方法完成解析逻辑。
  • 更改 XML 解析方式

在父类 ShopView中更改调用的解析器为我们新创建的 SAX 实现。

具体的代码可参考本文附件所带的示例代码。

修改好代码并按照上面的步骤从新运行数据分析,可以看到,现在的性能已经大为改观:

图 14. 修改代码后的运行统计视图
图 14. 修改代码后的运行统计视图
图 14. 修改代码后的运行统计视图

可以看到,XML 解析方法的运行时间已经由 0.5s 左右缩短到了大约 0.057s。

进一步的性能调优

如果你恰好足够幸运遇到了一位非常苛刻的用户,对目前的性能水平还不够满意。那我们就需要对现在的代码进一步进行优化以提高性能。

从新进行上面的步骤,首先以所有方法的执行时间进行排序。之后按照耗时的顺序从前往后进行分析。根据对前面几个方法的分析,我们发现,前面几个方法耗时较多的原因也都是因为最终调用了我们的 parseContent 方法。

按照上面的步骤,点击该方法以分析其具体执行状况:

图 15. 进一步分析 parseContent 方法
图 15. 进一步分析 parseContent 方法
图 15. 进一步分析 parseContent 方法

在该方法的 Selected method incokes 部分,我们可以看到,createParser 耗费了大部分的运行时间。我们可以从两方面入手进行性能调优,一是改善该段代码执行逻辑以增强性能,例如我们的第一轮修改中,从 DOM 的分析模式改为 SAX 模式。另外就是从代码的调用次数上入手,减少性能不佳代码的调用次数。例如在这里,通过进一步分析,具有性能瓶颈的方法用于产生用于 XML 分析的解析器,逻辑非常简单,但却被调用了 24 次。所以我们就可以从减少次数的角度来增强性能。

分析代码,我们可以创建一个 SAX 解析器的私有变量以在每次解析 XML 的过程中重用同一个解析器对象。以如下的方式修改代码:

清单 1. 重用 SAX 解析器对象的代码
privateSAXParser _saxParser; 

 protectedSAXParser createParser() throwsParserConfigurationException, SAXException 
 { 
    if(_saxParser == null) 
 { 
        SAXParserFactory f = SAXParserFactory.newInstance(); 
        f.setValidating(false); 
 _saxParser = f.newSAXParser(); 
 } 
    return_saxParser; 
 }

之后再次执行分析过程,就会发现,parseContent 方法的执行时间已经被缩减到了 0.017s 左右。通过我们的性能分析可调优,一个完成同样任务的方法,其执行时间已经从 0.5s 降低到了 0.017s,相信最苛刻的客户也可以接受这样的结果了吧。

本文通过一个示例说明了在 Eclipse 插件开发过程中如何使用 TPTP 进行性能分析和调优。可以看到,使用 TPTP 可以对程序运行时的各种数据进行直观化、图形化的分析。通过该工具的帮助,性能调优以及程序运行时状态的分析其实是一件非常容易的事情。


相关主题

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Open source
ArticleID=471284
ArticleTitle=使用 TPTP 对 Eclipse 插件进行性能剖析和调优
publish-date=03032010