JAVA性能优化—IBM JDK JVM参数设置
前一篇JVM的恩恩怨怨中,说了对WebSphere优化的关键点——因不同JDK而异。本文将描述IBM JDK下常用参数的设置。
-Xms:最小堆大小
-Xmx:最大堆大小
-Xminf and -Xmaxf:GC(垃圾回收)之后可用空间的最小值最大值
-Xmine and -Xmaxe:堆增长的最小最大值
-Xmint and -Xmaxt:垃圾回收占时间整个运行时间的比例,默认是5%。如果回收时间小于5%,那么它就缩减堆,反之增大。
一般来说只要对Xms和Xmx设置合理,后面的三对不用特别设置。可以看看http://publib.boulder.ibm.com/infocenter/javasdk/v5r0/index.jsp上heap expasion和heap shrinkage两章的说明,除非有下文的情况:
摘自Java性能优化的策略和常见方法
所以在应用正式上线的头一段时间,最好把GC日志打开,观察一下堆(heap)的增长(expasion)和收缩(shrinkage)。最佳的情况就是,每次回收后可用的堆大小占整个堆的50%左右。如果回收后才腾出30%不到的可用空间,那就该再调整一下上述的参数了。下图看起来直观一点,使用-verbose:size参数可以查看当前的默认值。
那为何不把Xms和Xmx设置成一样大,就像SUN的JDK所推荐的那样?
If the Garbage Collector cannot find enough garbage, it runs compaction. If the Garbage Collector finds enough garbage, or any of the other conditions for heap expansion are met , the Garbage Collector expands the heap.
因为IBM JDK采用的是标记(mark)-扫描(sweep)-标记-……-扫描-紧凑排列(compact),如果还不能提供足够的空间,扩展堆(expasion)。依次循环,直到达到最大堆大小。每次扩展前,那些长存的对象就被调整到堆的底部,每次扩展后需要再动的量就很少。所以如果把Xms设置成和Xmx一样,那么扫描和紧凑排列这么一个充满内存碎片的大堆的开销将大大高于从小扩展堆的开销。
这是由于IBM的GC特点造成的,而SUN的JDK采用的是分代回收的策略,所以就没有这种情况,反而会受益于堆大小一致。不过这么说起来,用了-Xgcpolicy:gencon,就应该把最小堆最大堆设置成一样咯。
在Gencon回收策略下,可以通过-Xmn来设置婴儿区域(Nursery或者叫young)的大小,通过-Xmo来设置长存区(tenured或者old)的大小。注意-Xmn不能和-Xmns/-Xmnx参数一起使用,-Xmo不能和-Xmos/-Xmox一起使用,否则会报错。前者就是把年轻代和长存代的大小固定了,而后两者就是设定两个部分最大最小的范围,默认情况下:
-Xmns是-Xms的25%或者64M(在JDK 5.0中默认是25%)
-Xmnx是-Xmx的25%或者64M(同上)
-Xmos是-Xmx减去-Xmns的大小
-Xmox是和-Xmx一样大
可见默认的年轻代太小了,生产环境中有必要改大一点。因为年轻代使用的是复制策略,所以回收速度相当快(minor gc),而长存代使用的是和optavgpause 策略相似的方式进行并发标志、扫描策略,回收速度比较慢(major gc)。理想情况是minor gc和major gc的比值在1:1010:1左右。(可以通过GC日志查看回收的区域)
gencon中年老期限(Tenure age)和倾斜比率(Tilt ratio)这两个参数是JVM自己动态调整的。
针对固定对象问题(Pinned Objects),使用-Xk -Xp参数设定kCluster和pCluster,Avoiding Java heap fragmentation with Java SDK V1.4.2. 或者我这篇IBM JDK的Java堆空间的碎片问题。
一些不常用的参数:
-Xloainitial<percentage> -Xloamaximum<percentage> :调整大对象区域(Large Object Area)的大小。分配总是先在SOA(Small Object Area)中分配,如果没有空间并且需要分配的大小大于64K,那么分配到LOA。默认情况下为-Xloainitial0.05 (5%),-Xloamaximum0.5 (50%),如果你的程序确实需要分配许多大对象的话(大于64K),那么可以调整LOA的初始百分比。
以上两点可以参考我这篇IBM JDK的Java堆空间的碎片问题,获得更详细的解释。
总结一下来说,对于optthruput和optavgpause,设置恰当的最大堆和最小堆,设置-Xk和-Xp避免碎片问题,如果程序需要分配大对象较多,那么调整一下LOA的大小;对于gencon,可以调大最小堆和最大堆接近,调整young区域的大小,LOA也可以视情况调整。subpool一般用不到,就不去研究了。
一些另外的信息
Default settings for the JVM
JVM environment settings
默认的Heapdumps是关闭的,调试的时候记得打开;默认的Javadumps on out of memory和Heapdumps on out of memory都是开启的,但是默认的dump位置是profile的所在目录,最好在管理控制台java进程中把IBM_HEAPDUMPDIR和IBM_JAVACOREDIR设置到别的目录,防止dump内容把WAS的文件系统撑爆,影响正常业务使用。
在Windows机器上,如果内存大于4G,记得开启/3GB参数,这样可以使JVM Heap可以设置的更大一些,接近2G-1,(其它的三部分可以扩展到另外的1G上去),但一般最大不超过1.7G。
更详细内容,可见http://publib.boulder.ibm.com/infocenter/javasdk/v5r0/index.jsp
或者下载dig60 http://www.ibm.com/developerworks/java/jdk/diagnosis/查看JVM这一块
Sun的JDK配置,可以参考JAVA性能优化—Sun Hotspot JDK JVM参数设置