相对于静态代码分析,Profiling 是通过收集程序运行时的信息来研究程序行为的动态分析方法。其目的在于定位程序需要被优化的部分,从而提高程序的运行速度或是内存使用效率。收集程序运行时信息的方法主要有以下三种:
- 事件方法:对于 Java,可以采用 JVMTI(JVM Tools Interface)API 来捕捉诸如方法调用、类载入、类卸载、进入/离开线程等事件,然后基于这些事件进行程序行为的分析。
- 统计抽样方法(sampling): 该方法每隔一段时间调用系统中断,然后收集当前的调用栈(call stack)信息,记录调用栈中出现的函数及这些函数的调用结构,基于这些信息得到函数的调用关系图及每个函数的 CPU 使用信息。由于调用栈的信息是每隔一段时间来获取的,因此不是非常精确的,但由于该方法对目标程序的干涉比较少,目标程序的运行速度几乎不受影响。
- 植入附加指令方法(BCI): 该方法在目标程序中插入指令代码,这些指令代码将记录 profiling 所需的信息,包括运行时间、计数器的值等,从而给出一个较为精确的内存使用情况、函数调用关系及函数的 CPU 使用信息。该方法对程序执行速度会有一定的影响,因此给出的程序执行时间有可能不准确。但是该方法在统计程序的运行轨迹方面有一定的优势。
目前市面上的 Java Profiler 工具采用的信息收集方法通常是以上三种方法的任意组合。
Profiler 工具功能简介
虽然市场上的 Java Profiler 工具有不少,但是基本功能大多相似,本节首先对这些基本功能进行介绍。
- 遥测(Telemetry):遥测是一种用来查看应用程序运行行为的最简单的方法。通常会有多个视图(View)分别实时地显示 CPU 使用情况、内存使用情况、线程状态以及其他一些有用的信息,以便用户能很快地发现问题的关键所在。CPU Telemetry视图一般用于显示整个应用程序的 CPU 使用情况,有些工具还能显示应用程序中每个线程的 CPU 使用情况。
Memory Telemetry视图一般用于显示堆内存和非堆内存的分配和使用情况。
Garbage Collection Telemetry视图显示了 JVM 中垃圾收集器的详细信息。
Threads Telemetry视图一般用于显示当前运行线程的个数、守护进程的个数等信息。
Classes Telemetry视图一般用于显示已经载入和还没有载入的类的数量。
- 快照(snapshot):应用程序启动后,profiler 工具开始收集各种执行数据,其中一些数据直接显示在遥测视图中,而另外大部分数据被保存在内部,直到用户要求获取快照,基于这些保存的数据的统计信息才被显示出来。快照包含了应用程序在一段时间内的执行信息,通常有两种类型的快照:CPU 快照和内存快照。
CPU 快照主要包含了应用程序中函数的调用关系及运行时间,这些信息通常可以在 CPU 快照视图中进行查看。
内存快照则主要包含了内存的分配和使用情况、载入的所有类、存在的对象信息及对象间的引用关系。这些信息通常可以在内存快照视图中进行查看。
- CPU Profiling:CPU Profiling 的主要目的是统计函数的调用情况及执行时间,或者更简单的情况就是统计应用程序的 CPU 使用情况。通常有两种方式来显示 CPU Profiling 结果:CPU 遥测和 CPU 快照。
- 内存 Profiling:内存 Profiling 的主要目的是通过统计内存使用情况检测可能存在的内存泄露问题及确定优化内存使用的方向。通常有两种方式来显示内存 Profiling 结果:内存遥测和内存快照
- 线程 Profiling:线程 Profiling 主要用于在多线程应用程序中确定内存的问题所在。一般包括三个方面的信息:
某个线程的状态变化情况
死锁情况
某个线程在线程生命期内状态的分布情况
- Profiling 的启动设置:类似于 eclipse 中 Run 和 Debug 的启动设置,进行 Profiling 之前也需要进行启动设置,包括:profiling 的模式(CPU profiling 或内存 profiling),信息获取类型(遥测,抽样统计或者 BCI )等等。
- Profiler Preference 设置:主要用于 Profiler 过滤器(选择需要关注的包、类)、取样间隔时间的设置等。
Java Profiler 工具介绍
本文接下来将对目前市场上常见的几种 Java Profiler 工具进行介绍。 TPTP TPTP(Test and Performance Tools Platform)是 eclipse 官方的 Profiling 工具插件。TPTP 提供了诸如测试,追踪(trace),性能测试,图形界面性能分析等功能。同时 TPTP 还是一个可扩展的开发平台框架,你可以对它加以扩展集成到你自己的产品中。TPTP 可以通过 Eclipse update Manager 或者是安装包进行安装,安装成功后会在 eclipse 中增加如下所示的按钮,另外一个专门的用于检查 TPTP profiling 结果的 perspective 也会添加进 eclipse 中,如下图所示:图 1. TPTP
CodePro Profiler
CodePro Profiler 是由 instantiations 公司推出的一款商用 eclipse 插件,它可以通过 Eclipse update Manager 进行安装或者是将安装包直接解压缩后保存在 eclipse 的指定目录下。与 TPTP 类似,安装成功后,有一个专门的用于查看 CodePro profiling 结果的 perspective 会添加进 eclipse 中,如下图所示:
图 2. CodePro
YourKit Profiler
YourKit Java Profiler 也是一款商用软件,支持的操作系统包括:Windows, Linux, FreeBSD, Mac OS X, Solaris 以及 HP-UX;支持的 IDE 包括:Eclipse, JBuilder, JDeveloper, NetBeans 以及 Intellij IDEA。安装成功且首次启动 YourKit Java Profiler 后,会弹出一个对话框,让用户选择 YourKit Java Profiler 要集成进的 IDE,并指定该 IDE 的安装路径,点击”Install Plugin”按钮并集成成功之后,Eclipse 中会出现如下图标,用户就可以从 Eclipse 中启动 Profiling,但是 profiling 的结果需要在 YourKit Java Profiler 中进行查询,如下图所示:
图 3. YourKit JProfiler
JProfiler
JProfiler是由 ej-technologies 推出的一款商用软件,支持的操作系统有:Windows, Linux, Mac OS X, FreeBSD, Solaris, AIX 以及 HP-UX;支持的 IDE 包括:Eclipse, NetBeans, Intellij IDEA, JBuiler 以及 JDeveloper。安装成功并首次启动 JProfiler 后,会弹出一个设置界面,当完成左栏所示的那些步骤后,Eclipse 中就会出现如下图标,用户就可以从 Eclipse 中启动 Profiling。与 YourKit Java Profiler 类似,profiling 的结果需要在 JProfiler 中进行查询,如下图所示:
图 4. JProfiler
Java Profiler 工具比较
本章节将从如下几个方面对上述工具进行比较:
- 与 Eclipse 的集成性
- 遥测种类
- CPU 快照包含的统计数据类型
- 内存快照包含的统计数据类型
- 源代码定位功能,即在快照中选中某个类、成员变量或者方法时,可以在源代码中定位到对应的定义。
- 快照操作,主要从快照的获取、快照的保存及快照的比较这三方面进行比较。
- 性能,在 sampling 模式下,这些工具的性能相差不大,这里主要比较在 BCI 模式下的性能。
- 健壮性,采用 CodePro Profiler 对比较大的应用程序进行 profiling 时,很容易出现栈溢出的错误。