Eclipse插件TPTP-程序Profile与分析工具详细教程

来源:http://blog.csdn.net/zq602316498/article/details/38796095

TPTP简介

Eclipse Test & Performance Tools Platform 是Eclipse的一个顶级工程(Top-Level Project),TPTP项目封装了一大堆公共的操作接口与数据,甚至一个远程执行环境,以供其它的TPTP工具使用。另外,它还提供了扩展点以方便进 行定制编码。实际上就是一个依托于Eclipse的JAVA的Profile与分析工具。可以进行程序执行时间的统计分析、内存的监控、对象调用的分析 等。

TPTP插件安装

下面简单说一下安装和使用的步骤:

首先登陆tptp插件的官方地址:http://www.eclipse.org/tptp/

点击图中的最新版本“TPTP 4.7.2”,打开下载页面。

此时我们有两种安装方式全安装和以插件方式安装。

全安装TPTP all-in-one package 的安装方式,里面包含了整合了TPTP的完整的Eclipse软件,下载下来以后直接解压打开Eclipse 就可以使用。

插件方式的安装即 TPTP Plugins for Eclipse 只包含了TPTP插件,需要自己手动安装。最新版TPTP-4.7.2只支持 Eclipse SDK 3.6.2,因此你必须使用这个版本的Eclipse才可以,TPTP依赖的运行环境和插件都需要自己手动下载并安装。

强烈建议选择全安装的方式,这样安装过程中会遇到较少的问题。笔者就是因为自己手动安装,出了好多问题,折腾了半天只好改用全安装的方式。

all-in-one package 下载完成之后,解压到任意目录,打开Eclipse,可以看到如下图中所示的profile按钮,就表示可以使用profile的功能了!

使用TPTP分析Java程序

执行时间分析

选中某一Java程序,点击右键,选择【Profile As】->【Java Application】选项,打开分析配置菜单:


在弹出的配置菜单中,选择【Profile Settings】选项,选中【Execution Time Analysis】选项,点击【OK】。此时Java程序会自动执行,并且tptp会记录其执行的过程。(这个过程要比单纯的执行程序要慢很多 --)

Collect method CPU time information:剖析器都可以收集 CPU 花在执行剖析方法的时间。这不同于上述的任何一种方法,因为 I/O 与等待时间并没有包含在 CPU 时间之中。

当程序执行完成之后,会自动弹出tptp的【Profiling and Logging perspect】窗口,我们可以看到分析完成后的数据表。

此时tptp会自动给出时间消耗前十的方法,并给出详细的调用时间信息。我们可以通过这些信息来判断程序中哪些地方存在着性能问题,进而有的放矢的进行优化。

图中各列指标的含义如下:

Session summary 项提供了拥有最高基底时间的最重要十种方法的概述。但是,所有的数据都是从 Execution Statistics 项中获得的。在这里您可以找到关于方法执行及其统计的具体信息:访问的时间,平均花费的时间,累积的时间等等。

Average Base Time:它是完成一个方法所需要的平均时间。所以,平均看来,这就是一个方法需要完成单个革新所需要的时间(如上面所述的那样,它排除了该方法调用子方法所需要的时间,更具体的说,排除了未筛选子方法的时间)。
Base Time:这就是完成一项方法所需要的总体时间。这就是我们花在该方法上所有时间的混合体(排除了对其他未筛选方法的调用)。

Base Time
For any invocation, the base time is the time taken to execute the invocation, excluding the time spent in other methods that were called during the invocation.

这个时间是执行这个方法是消耗的时间, 不包括这个方法里面调用其他子方法的时间。  例如方法A, 里面调用方法B, 方法c 各一次, 同时调用方法d10次, 那么这个base time 时间是不包括  对方面b,c,d等等的时间调用的时间。 就是纯粹花在方法A的时间
Cumulative Time:累计 CPU 时间代表了花在执行特定方法之上的总体 CPU 时间。但是,JVM 提供的数据的组成性变得更加粗糙,但是却更需要它。结果,如果时间要少于 JVM 所报告的单个特定平台的单元,那么 CPU 时间可能报告为零。同样,CPU 时间不会考虑其他类型的性能瓶颈,例如那些涉及到的交流类型以及 I/O 访问时间。

结论是,基底时间通常可以当作性能瓶颈降低的工具。

Cumulative Time
For any invocation, the cumulative time is the time taken to execute all methods called from an invocation. If an invocation has no additional method calls, then the cumulative time will be equal to the base time.

这个时间就是 执行一个方法上的总的时间,  包括方法调用若干子方法的时间等。

 

Average  xxx 时间    是这个方法的相关时间   / 调用次数的时间

 

总的来说,平均的基底时间好像是决定什么方法降低系统速度的关键数据点。但是,虽然平均基底时间可能会精确指出花费长时间执行的方法,但是并没有考 虑到访问一个方法的次数。对比一下:一个只运行一次的方法并花费 5.0 秒,或者另一个运行 1000 次并花费 0.5 秒?第一种方法的平均基底时间是 5.0 秒,而第二个方法的平均基底时间是 0.5 秒。但是,第一种方法的基底时间是 5.0 秒,而第二种方法的基底时间是 500 秒。将程序的运行时间降低 500 秒要比仅仅降低 5 秒显著的多。因此您可以毫不犹豫地说出,由于基底时间差异的存在,第二种方法要比第一种方法获得更多的关注。因此基底时间是降低一个程序中性能瓶颈的主要 关注点。因为基底时间代表了整个程序运行的混合物,通常所说的降低基底时间就相当于说降低运行时间。

当基底时间只代表了执行方法本身所花的时间(除了对其他方法的访问),累计时间则代表了执行一种方法所花费的总体 时间,包括子访问。所以,举个例子,在单一线程的程序之中, main(…) 方法的累计时间相当于程序中所有其他方法的所有基底时间的总和,因为 main(…) 方法就是程序的起始点,因为它就是所有方法访问的起始点。因此,它就相当于总体的程序运行时间。

在对执行统计数据有了详细的理解之后,让我们看一下分析性能问题的具体形式。为了得到调用什么特定方法的更好理解,以及特定的方法是从哪里调用的, 双击 Execution Statistics 项中想要的方法。这将会打开 Method Invocation Details 项,如下图所示。

Method Invocation Details 项就是每一个方法的统计数据。

项中的第二个表是 Selected method is invoked by,这将会列出程序运行期间访问选择方法的所有方法。

第三个表, Selected method invokes,将会列出选择方法所访问的所有方法。

 

接下来需要注意的一点是 Call Tree 项,当您剖析 Execution Flow 剖析选项时它才可用。

Call Tree 项会为访问特定线程的所有方法分解访问调用。

表格中的第一层次项目是程序运行期间展开的线程。

在它下面是方法调用的混合体,以及树形结构前面层次所访问方法的下一个层次的方法。

在最顶级的层次上,每一个线程的 累计时间 代表了线程在程序中运行的总体时间。那些拥有更高累计时间的线程,就是分析和优化的潜在对象。

Percent Per Thread 字段代表了执行一个方法所花费的总体时间,它用执行线程所花费总体时间所占的百分比来表示。它代表了一个最顶级方法对线程调用的总体累计时间(就是花在执 行线程上的总体时间)。它还提供了其他的统计数据,例如完成对线程执行方法的最大时间,最小时间以及平均时间,以及访问的总体数量。
在顶部的访问树表之下,是方法调用栈的表格,它显示了访问树表中当前所选中项目每一个方法调用的栈的内容。可得到栈的数量,与所列出访问的数量相等。在向分析特定的方法调用实例时这一点十分的重要。
最后,您可以右击方法条目并从任意的视图中选择 Open Source。如果相关的 Java 文件出现在工作区中,工作台文件将会打开,而方法定义也会得到定位。当性能瓶颈得到识别之后,您就可以编辑它们,然后再次进行剖析以查看它们之间的差异。

内存占用分析

选中这个选项,您就能够选择 Object Allocations 视图中的类,并识别这些对象是从哪些方法中创建的。选中 Track Object Allocation Sites 选项的唯一缺点在于,这会极大程度地增加生成的剖析数据的量。如果剖析性能受到了影响,或者工作台响应性受到了影响,那么可以考虑清除这些选项或者使用更新的筛选规则集来降低数据量。


Live instances :被引用的instance数量,instance没有被GC收集
Active size : Live instances 的Size
Total instances and total size:所有对象实例的数量和占用内存大小
Average age:age—GC的次数, Average age=(所有对象的年龄和)/(对象个数)

识别内存泄漏: Live instances相对比较大、持续增长、GC之后age 增长,可能存在内存泄漏,通过Alloction Details视图查看可能的泄漏位置。

线程分析

选择【Thread Analysis】可以对线程的行为进行追踪。

Thread Analysis 视图被分解为了三项 :
Thread Statistics:一个程序启动的每一个线程的统计数据表,不管这些线程是过去的还是现在的。列出的信息还包括线程表格;总体运行时间,等待时间以及堵塞时间;每一个线程堵塞和死锁的数量。
Monitor Statistics:提供了关于类统计数据的具体信息,包括私人监视类的堵塞和等待统计数据。
Threads Visualizer:提供了目标程序中由状态所剖析的所有线程的可视化代表。
所有视图中的线程是由线程组所组织的。线程分析视图中的数据只会在接收到新的线程时间的时候才会更新数据。如果它出现了就好像数据没有得到更新时,这是因为没有接收到新的线程事件,而数据仍然处于它的前一个状态之中。
列出的线程名就是传递给 Thread(String name) 构造器的名字,或者使用 Thread.setName 方法来进行设置。在目标程序中调用这种方法能更容易的识别线程。

线程统计数据是基于所有的 Java 线程来收集的,它包含了 VM 线程,并且可能包含了程序构造器或者程序框架所使用到的线程。幸运的是,您可以选择线程筛选图标(是一个中间黄色箭头划过垂直绿色线的三个箭头 ),来从视图中筛选出去那些您不感兴趣的线程,并清除掉那些不想要的线程。
七种线程状态分别是 :
运行
睡眠: 这种状态下清晰调用 sleep 方法
等待: 这种状态下清晰调用wait 方法,并等待在其监视对象上的 notify 或者 notifyAll 访问
堵塞: 对一个被对象堵塞实例的引用,该对象被另一个线程所使用(例如,一个线程在一个同步化的状态下维护对象监视器的线程)
死锁: 对于目标程序的每一个线程,在每一个线程的层次上收集统计数据。当两个或者更多的线程都含有资源时就会发生死锁现象,其中资源关系图包含了一个循环(这就是说,所有的死锁线程都需要它们所不能获得的额外资源,而不用释放需要资源的其他死锁线程 )。
停止
未知
在 Java 中,在很多种情况下都可以发生死锁现象,例如 :
在两种线程中,两个类中的同步化方法会试着调用同步化的方法。
当一个线程同步化资源 A 并试着在第二个资源 B 上进行同步化,同时第二个线程同步化资源 B 并试着同步化资源 A 时就会发生死锁现象。

Thread Statistics

该项列出了程序的整个生命周期内,当前所运行的所有的线程。线程就算在程序终止以后仍然停留在表格之中。该视图列出了运行时间、等待时间以及堵塞的时间。其中 运行时间 被定义为线程的总体运行时间,减去等待或者堵塞之后的时间。等待时间 被定义为线程花在等待监视上的时间,而 Blocked time 就是线程花在被其他线程监视器拥有权堵塞上的总体时间。另外,还有一些记录的数量 :堵塞数量 以及 死锁数量 分别是线程生命周期之内线程堵塞或者死锁的次数。

Monitor Statistics

Thread Analysis 视图中的第二项是 Monitor Statistics,如下图所示。Java 中所有的对象都有一个相应的监视器,这是 Java 中所有并发操作的基础。当您进入到一个同步化块的内部时,就会调用监视器,或者在调用 wait 或者 notify 方法时,会分别等待可用性的附属或者信号。该项提供了线程-线程基础之上的监视器状态

Thread Statistics 表格包含了剖析程序中的一系列线程,以及来自首项的线程的各种统计数据。选择 Thread Statistics 表格中的一个线程,来显示线程所引用的监视器,包括这些监视器的各种统计数据。然后您可以选择监视器以打开关于其类的信息,包括监视器访问者的块与统计数 据,还有计时与对象信息。这就支持您去识别特定的对象。

Threads Visualizer

在如上图所示的 Threads Visualizer 项中,线程状态由变化的背景栏和线性模式代表。线程根据线程组和线程名来分组。图的 x 轴代表了时间,它的范围可以使用放大或者缩小按钮来进行调整。

表格的每一行都包含了一个代表线程执行情况的工具栏。在每一个栏中都是事件的持续性列表,它代表了线程状态的更改。您可以双击一个事件以在 Call Stack 视图中显示它的访问栈,而且您可以使用 Threads Visualizer 项右上角的 Select Next Event 和 Select Previous Event 按钮,来从一个事件移动到另一个事件。
在图中, Waiting 和 Blocked 状态是由点线代表的,而 Deadlocked 与 Stopped 状态是由一条实线表示的。对于识别性能问题的程序开发员来说,最重要的是 Deadlocked (红色), Waiting (橙色)与 Blocked(黄色)。
一个重要的 UI 注意点:当一个线程终止,它会继续在表格上维护一个暗灰色的代表(而不是从图表中完全地消失掉),可能与预期的行为相反。

线程分析工具栏上的按钮用于将注意力转自或者转至特定的线程。从左到右,,按钮分别是:Legend, Show Call Stack, Reset Timescale,Zoom In/Out,Select Next/Previous Event,Select Next/Previous Thread,Group Threads, Filter Threads 以及 Visualize Thread Interactions。它们中的大多数是不言自明的:例如, Next/Previous Thread 按钮会更改当前选中的线程,而 Select Next/Previous Event 按钮则会将游标移动到下一个项目,或者当前选中线程的前一个事件。另外,您可以根据自己的需要来分组并筛选线程。

当您使用线程剖析功能时,有几点您需要进行考虑一下 :
对于处于工作-睡眠循环状态下的线程,它需要多长的时间来完成循环的工作阶段,又需要多久的时间来完成睡眠阶段呢 ?
对于独立于外部性资源的线程来说,它们堵塞了多长时间以等待可用的资源 ?
在输入-处理-输出型的程序中,例如 Web 程序,不同的线程需要多成的时间以响应用户输入,处理数据,以及产生相应的输出 ?
有一些线程会阶段性地工作,以检查一种状态或者执行一项功能,然后返回至睡眠状态。线程分析允许您使用 Threads Visualizer 来观察这些关系。
您可以使用剖析功能来监视生产者-消费者和读者-作者关系。
线程剖析功能提供了各种的视图,来分析程序线程的性能与行为。这些视图允许您去收集信息,并分析程序执行的各个方面,以得到失败状况的潜在性瓶颈。

筛选

在选择剖析按钮之前,适当的筛选规则应该已经就位,这一点非常重要。大量的剖析数据是作为剖析过程的一部分生成的,因为每一个单个的方法调用,对象分配或者线程事件,都需要生成、转移和处理一个事件。
剖析数据的净数量有时可能是巨大的,不论是对于执行程序来说,还是对于工作台本身来说,如此巨大的数量都是吃不消的。但是,这些数据中只有一部分对于分析 目的是有用的。幸运的是,剖析的数据提供了一个方法去筛选去除掉一些不相关的信息,这样您就可以为剖析程序降低代理数据的量。
例如,在剖析一个 Java 程序的过程中,您可能只关注那些您的程序的方法,以及一些不在执行时间之中的像 java.*、sun.* 等等标准 Java 语言包。使用特定于程序中类的一种筛选非常重要,它可以尽可能多地从外部类中降低剖析的工作负荷。
通过双击【Java Profiling -JRE1.5***】可以打开筛选设置窗口来进行设置,如下图。

在服务器端测试应用程序的性能

当然也可以对WEB系统进行测试,笔者没有使用过这方面的功能,只能找了点资料简单介绍一下步骤,只能是提供一下思路,具体能不能用还要以后有时间去实践。

1、在Eclipse中新建“Dynamic Web Project”(JavaEE视图)。
2、在项目中新建JavaBean和JSP,以tomcat自带的numguess.jsp为例。
3、在Eclipse中新建Server配置,选择tomcat5.5。
4、运行示例程序。
5、在系统环境变量PATH后添加:%Eclipse%\plugins\org.eclipse.hyades.execution._%Version%
6、重启Eclipse。
7、右键点击JSP文件,选择Profile As /Profile on Server。
8、在Profile on Server对话框中添加要测试的类。
9、分析测试结果。

发表评论