时间:2006-11-22 作者:John Ferguson Smart 浏览次数: <script language="JavaScript" src="/beadevcount.jsp?d_id=162489" type="text/JavaScript"></script> 1196 本文关键字:IDE, Java, Eclipse, Eclipse Callisto, profiling, performance, TPTP |
|
Eclipse(Eclipse 3.2)的最新版本带有Callisto,一套丰富的针对Eclipse 3.2的可选插件。Callisto包括一个功能强大的分析工具,此工具称为Eclipse测试与性能工具平台,简称TPTP。TPTP提供了一套功能全面的开源性能-测试和分析工具,包括集成的应用程序监控、测试、跟踪和分析功能,以及静态代码分析工具。对于在各类Java应用程序中找出和识别性能问题,分析工具的价值是不可估计的。在本文中,我们将探讨如何使用TPTP来保证获得高质量和高性能的代码(甚至是在单元和集成测试中)。
安装TPTP
安装TPTP最容易的方式是使用Remote Update站点(参见图1)。打开Remote Update窗口(Help -> Software Updates -> Find and Install),然后选择Callisto Discovery Site。Eclipse将建议安装Callisto插件集。TPTP工具列在“Testing and Performance”下面。最容易也是最耗时的选择,就是安装所有建议的插件。即使不安装整个Callisto工具集,您仍然需要安装一些其他TPTP需要的组件,例如"Charting and Reporting"、"Enabling Features"和"Data Tool Performance"。
图 1.从远程站点安装TPTP
分析Java应用程序
测试与性能工具平台基本上是一套分析工具。分析应用程序通常涉及到观察应用程序在压力之下的处理方式。这样做的一种常见方式是对已部署的应用程序运行一组负载测试,然后使用分析工具来记录应用程序的行为。接着,可以对结果进行研究来调查任何性能问题。这些事情通常是在项目结束时进行的,因为此时应用程序几乎已经准备好进入生产阶段了。
TPTP非常适合这类任务。一个典型的用例是使用像JMeter这样的工具来运行负载测试,然后使用TPTP归纳工具记录和分析性能统计数据。
然而,这并非使用TPTP分析应用程序的唯一方式。通常,越早进行测试,后面遇到的问题就越少。借助TPTP,您可以在很多上下文中分析代码,包括JUnit测试用例、Java 应用程序和web应用程序。而且它很好地集成到了Eclipse IDE中。所以,没有理由不在早期开始初步性能测试和分析工作。
TPTP让您可以测试应用程序行为的几个方面,包括内存使用(创建了多少对象,这些对象的大小如何)、执行统计数据(应用程序在哪些地方所花的时间较多)和测试覆盖(测试期间执行代码的确切数量)。每个方面均可提供有关应用程序性能的独立信息。
不管怎么说,内存泄漏可能而且的确存在于Java中。创建(并保存)不必要的对象会增加对内存的需求,并加重垃圾收集器的工作负担,这都会损害应用程序的性能。而且,如果运行应用程序的服务器的持续正常运行时间很长,累积下来的内存泄漏可能最终导致应用程序崩溃或服务器停止运行。这些都是留心应用程序内存泄漏情况的充分理由。
根据80-20经验法则,80%的性能问题出现在20%的代码中。或者,换句话说,只要把精力集中在应用程序中执行最经常的部分上,就可以花费相对较少的气力使性能有实质性的提高。在这种情况下,执行统计数据就可以派上用场了。
除此以外,TPTP还提供一些基本的测试覆盖数据。尽管这些统计数据不如Cobertura或Clover这样的专用工具提供的完整,您仍然可以通过它们快速了解性能测试正在有效地测试哪些方法。
在本文中,我讨论的测试种类同样是没有经过优化的。优化涉及到使用像缓冲这样的技术对应用程序性能进行微调。这是一项对技术要求很高的操作,最好留到项目的最后完成。
这里所讨论的这种初步性能测试和分析仅仅包括,确保应用程序从一开始就正确执行,以及没有编码错误或糟糕的编码实践会在后面的阶段中对性能产生不利的影响。事实上,修复内存泄漏和避免不必要的对象创建并不是优化——这只不过是调试,而且同样应该尽可能早地完成。
让我们通过使用一些单元测试来分析一个类的方式开始。可以分析常规的单元或集成测试,或者编写针对性更强的面向性能的测试。通常,您应该尝试分析与生产代码最接近的代码。许多人使用模拟对象来代替DAO对象进行单元测试,使用这项功能强大的技术可以加速开发生命周期。如果使用这类方法,一定要使用这些测试来运行分析工具,它可以揭示有关内存使用和测试覆盖的有用信息。然而,性能测试的价值是有限的,因为对于与数据库相关的应用程序来说,其性能往往是由数据库的性能所决定的,所以在这个上下文中,应该进行所有重要的性能测试。简而言之,不要忘了分析基于实际数据库而运行的集成测试。
出于本文的需要,我们将对以下类进行测试,这个类代表了一个到库目录的简单接口。
interface Catalog { List<Book> findBooksByAuthor(String name); List<Book> findAllBooks(); }
基本的单元测试如下:
public class CatalogTest extends TestCase { ... public Catalog getCatalog() { ... } public void testFindBooksByAuthor() { List<Book> books = getCatalog().findBooksByAuthor("Lewis"); } public void testLoadFindBooksByAuthor() { for(int i = 0; i < 10; i++) { List<Book> books = getCatalog().findBooksByAuthor("Lewis"); } } public void testFindAll() { List<Book> books = getCatalog().findAllBooks(); } }
您需要做的第一件事情就是建立一个分析。在Eclipse主菜单中选择"Run -> Profile",这将打开一个向导,您可以在其中配置不同种类的测试分析,如图2所示。
图 2. 创建一个TPTP分析
在这个例子中,我们感兴趣的是JUnit测试分析。双击这一项;向导应该为每个单元测试类创建新的项。TPTP相当灵活,您可以在此屏幕中配置各个选项。例如,在Test选项卡上,可以单独分析单元测试类,也可以按照项目或软件包对它们进行分组。在Arguments选项卡上,可以指定运行时参数,而在Environment选项卡上可以定义环境变量。在Destination选项卡中,可以指定一个外部文件,用于保存分析数据以供以后使用。但是,最有用的是Monitor选项卡(参见图3),可以在上面指定要记录和研究的性能相关数据:
- Basic Memory Analysis(基本内存分析):这个选项用于记录内存使用的统计数据,包括对象实例的数量和已经使用的全部内存。
- Execution Time Analysis(执行时间分析):这个选项用于记录性能数据——即应用程序分别在每个方法上所花的时间长短。
- Method Code Coverage(方法代码覆盖):这个选项用于通知在测试期间执行了哪些类和方法。
图 3: 在Monitor选项卡上定义要记录数据的类型。
您可以直接从这个窗口运行分析工具,也可以使用位于要分析的测试类上的上下文菜单,方法是选择Profile As菜单项(参见图4)。
图 4:可以使用上下文菜单运行TPTP分析工具。
运行分析工具可能要花上一段时间,这取决于测试用例的大小。完成之后,Eclipse将显示一个Profiling Monitor视图,可以在其中显示每种类型分析的结果的详细信息(参见图5)。
图 5: 分析结果
Memory Statistics视图显示了应用程序创建的对象的数量。结果可以按照软件包来组织(以树视图的形式),或者显示为类或实例的一个列表。这些数据可以让您了解每种类型创建了多少个对象;应该对创建的对象(特别是高级对象,例如域对象)不正常的高数量持怀疑态度。
用于检测内存泄漏的另一个有用工具是Object References视图。为了获得这些数据,您需要激活引用收集。启动分析之后,点击monitoring项,然后在上下文菜单中选择Collect Object References(参见图6)。接下来,通过上下文菜单(Open with -> Object References)打开Object References视图。您将获得一个类的列表,它带有对每个类的引用的次数。这可以为可能的内存泄漏提供一些线索。
图 6: 激活引用收集
如图7所示,从Execution Statistics视图可以清楚地了解到应用程序执行到了哪里。"organization by"软件包可以帮助您找出执行时间最长的类和方法。点击一个方法将打开Method Invocation Details视图,它将显示有关方法被调用次数、调用地点以及它本身调用了哪些其他方法的更详细信息。尽管与一些可以向下发掘到源代码本身的商业工具相比,这个视图与源代码视图的集成度没有那么高,但是它还是可以给出一些重要线索,帮助您找出执行错误的方法。
图 7: Execution Statistics视图
Coverage Statistics视图(参见图8)提供的信息是关于,您刚刚运行的测试用例使用了(因此至少在某种程度上测试了)哪些方法。覆盖统计数据是一项优秀的功能,尽管它们提供的信息的详细程度还无法与像Cobertura、Clover和jcoverage这样的专业覆盖工具相提并论(它们可以提供行精度的覆盖数据,以及行和分支覆盖的统计数据)。尽管如此,它也有自身的优点,那就是可以提供实时的覆盖结果,而目前,只有商业的代码覆盖工具,例如Clover和jcoverage,才能提供行级别的覆盖报告和完整的IDE集成。
图 8: Coverage Statistics视图
静态分析工具
在TPTP工具箱中,另一件有趣的工具就是静态分析工具。Java静态分析工具,例如PMD,允许通过基于一组代码预定义规则和最佳实践检查来检查代码,从而自动验证代码质量。现在,TPTP也包含一个静态分析工具。除了提供它自己的一组静态分析规则之外,这个工具还可以提供一个一致的接口,其他工具厂商可以在这个接口中集成他们自己的规则。
要对代码进行静态分析,需要创建分析配置。在Java视图或Analysis图标中,使用上下文菜单打开Analysis窗口,它现在应该出现在工具栏上(参见图9)。分析配置决定了要分析的代码(Scope)和应该遵循的规则(Rules)。有71条规则可供选择,例如"Avoid casting primitive types to lower precision"和"Always provide a break at the end of every case statement"。您还可以使用预定义的规则,例如"Java Quick Code Review"(在这里,71条规则中只有19条适用)。
图 9:建立静态分析规则
要分析代码,使用工具栏中的Analysis图标。分析不是实时完成的,就像一些其他的类似工具一样,例如Checkstyle。然而,给出的结果很清晰(参见图10):错误在源代码视图中标出,并且按照错误类型,以树视图的形式在Analysis Results视图中列出。"Quick Fix"是一项优雅的特性,它出现在错误类型的上下文菜单中,而且如果可能,它可以自动为您纠正问题。
图 10: 静态代码分析结果
结束语
Eclipse测试与性能工具平台是Eclipse IDE工具箱中极具价值的部分。它支持的性能测试的范围很宽,这有助于从第一个单元测试开始,就确保获得高质量和高性能的代码。
TPTP无疑还比不上一些可用的商业工具,例如OptimizeIt和JProbe,后者的报告和分析功能要更加完善,而且表示通常更加精练。然而,商业的分析工具往往非常昂贵,而且很难在最严峻的环境中来验证它们的使用情况。尽管TPTP还相对较为不成熟,它仍然可算作一款功能强大的产品,毋庸置疑,它可以提供对于许多项目来说不可或缺的有价值的分析数据。
参考资料
作者简介 | |
John Ferguson Smart 从1991年起涉足IT行业,从1999年起开始参与J2EE开发。 |