5.3 实战:Eclipse运行速度调优

很多Java开发人员都有这样一种观念:系统调优的工作都是针对服务端应用而言,规模越大的系统,就越需要专业的调优运维团队参与。这个观点不能说不对,5.2节中笔者所列举的案例确实都是服务端运维、调优的例子,但服务端应用需要调优,并不说明其他应用就不需要了,作为一个普通的Java开发人员,前面讲的各种虚拟机的原理和最佳实践方法距离我们并不遥远,开发者身边很多场景都可以使用上面这些知识。下面通过一个普通程序员日常工作中可以随时接触到的开发工具开始这次实战。

5.3.1 调优前的程序运行状态

笔者使用Eclipse作为日常工作中的主要IDE工具,由于安装的插件比较大(如Klocwork、ClearCase LT等)、代码也很多,启动Eclipse直到所有项目编译完成需要四五分钟。一直对开发环境的速度感觉不满意,趁着编写这本书的机会,决定对Eclipse进行“动刀”调优。

笔者机器的Eclipse运行平台是32位Windows 7系统,虚拟机为HotSpot VM 1.5 b64。硬件为ThinkPad X201,Intel i5 CPU,4GB物理内存。在初始的配置文件eclipse.ini中,除了指定JDK的路径、设置最大堆为512MB以及开启了JMX管理(需要在VisualVM中收集原始数据)外,未做其他任何改动,原始配置内容如代码清单5-3所示。

代码清单5-3 Eclipse 3.5初始配置


-vm

D:/_DevSpace/jdk1.5.0/bin/javaw.exe

-startup

plugins/org.eclipse.equinox.launcher_1.0.201.R35x_v20090715.jar

—launcher.library

plugins/org.eclipse.equinox.launcher.win32.win32.x86_1.0.200.v20090519

-product

org.eclipse.epp.package.jee.product

—launcher.XXMaxPermSize

256M

-showsplash

org.eclipse.platform

-vmargs

-Dosgi.requiredJavaVersion=1.5

-Xmx512m

-Dcom.sun.management.jmxremote


为了要与调优后的结果进行量化对比,调优开始前笔者先做了一次初始数据测试。测试用例很简单,就是收集从Eclipse启动开始,直到所有插件加载完成为止的总耗时以及运行状态数据,虚拟机的运行数据通过VisualVM及其扩展插件VisualGC进行采集。测试过程中反复启动数次Eclipse直到测试结果稳定后,取最后一次运行的结果作为数据样本(为了避免操作系统未能及时进行磁盘缓存而产生的影响),数据样本如图5-2所示。

figure_0162_0062

图 5-2 Eclipse原始运行数据

Eclipse启动的总耗时没有办法从监控工具中直接获得,因为VisualVM不可能知道Eclipse运行到什么阶段算是启动完成。为了测试的准确性,笔者写了一个简单的Eclipse插件,用于统计Eclipse的启动耗时。由于代码很简单,并且本书不是Eclipse RCP开发的教程,所以只列出代码清单5-4供读者参考,不再延伸讲解。如果读者需要这个插件,可以使用下面代码自行编译或者发电子邮件向笔者索取。

代码清单5-4 Eclipse启动耗时统计插件


ShowTime.java代码:

import org.eclipse.jface.dialogs.MessageDialog;

import org.eclipse.swt.widgets.Display;

import org.eclipse.swt.widgets.Shell;

import org.eclipse.ui.IStartup;

/**

*统计Eclipse启动耗时

*@author zzm

*/

public class ShowTime implements IStartup{

public void earlyStartup(){

Display.getDefault().syncExec(new Runnable(){

public void run(){

long eclipseStartTime=Long.parseLong(System.getProperty("eclipse.startTime"));

long costTime=System.currentTimeMillis()-eclipseStartTime;

Shell shell=Display.getDefault().getActiveShell();

String message="Eclipse启动耗时:"+costTime+"ms";

MessageDialog.openInformation(shell,"Information",message);

}

});

}

}

plugin.xml代码:

<?xml version="1.0"encoding="UTF-8"?>

<?eclipse version="3.4"?>

<plugin>

<extension

point="org.eclipse.ui.startup">

<startup class="eclipsestarttime.actions.ShowTime"/>

</extension>

</plugin>


上述代码打包成jar后放到Eclipse的plugins目录,反复启动几次后,插件显示的平均时间稳定在15秒左右,如图5-3所示。

figure_0164_0063

图 5-3 耗时统计插件运行效果

根据VisualGC和Eclipse插件收集到的信息,总结原始配置下的测试结果如下。

整个启动过程平均耗时约15秒。

最后一次启动的数据样本中,垃圾收集总耗时4.149秒,其中:

●Full GC被触发了19次,共耗时3.166秒。

●Minor GC被触发了378次,共耗时0.983秒。

加载类9115个,耗时4.114秒。

JIT编译时间为1.999秒。

虚拟机512MB的堆内存被分配为40MB的新生代(31.5的Eden空间和两个4MB的Surviver空间)以及472MB的老年代。

客观地说,由于机器硬件还不错(请读者以2010年普通PC机的标准来衡量),15秒的启动时间其实还在可接受范围以内,但是从VisualGC中反映的数据来看,主要问题是非用户程序时间(图5-2中的Compile Time、Class Load Time、GC Time)非常之高,占了整个启动过程耗时的一半以上(这里存在少许夸张成分,因为如JIT编译等动作是在后台线程完成的,用户程序在此期间也正常执行,所以并没有占用了一半以上的绝对时间)。虚拟机后台占用太多时间也直接导致Eclipse在启动后的使用过程中经常有不时停顿的感觉,所以进行调优有较大的价值。