Java性能优化权威指南-读书笔记(四)-JVM性能调优-延迟

延迟指服务器处理一个请求所花费的时间,单位通常是ms、s。html

本文主要讲下降延迟能够作的服务器端JVM优化。java

JVM延迟优化

新生代

新生代大小决定了应用平均延迟服务器

若是平均Minor GC持续时间大于应用程序平均延迟性要求,能够适当减少新生代空间大小;多线程

若是Minor GC频率大于应用程序平均延迟性要求,能够适当增大新生代空间;并发

老年代

老年代大小决定了应用最差延迟性能

FullGC频率大于应用程序最大FullGC频率要求,能够适当增大老年代空间大小;优化

FullGC持续时间大于应用程序最差延迟性要求,可使用CMS垃圾收集器;ui

CMS收集器调优

CMS主要特性

CMS为老年代收集器,收集线程能与应用程序线程实现最大的并行度,下降了延迟。spa

CMS并不进行压缩,因此老年代使用空闲列表分配内存,在必定程度上增长了新生代晋升老年代时,耗费的时间。线程

但一旦老年代溢出就会触发Stop-The-World压缩式垃圾收集。

因此,CMS的优化大概有下面几点:

1. 避免用尽老年代空间;

2. 解决老年代碎片化问题,解决方法包括压缩、MinorGC回收原则;

3. 下降初始标记阶段和从新标记阶段占用的时间,由于这两个阶段应用程序线程会被阻塞;

Survivor空间调优

调整Survivor空间,是为了让其有足够空间容纳存活对象足够长的时间,直到几个周期后对象老化,解决上面的第1、二条问题。

Survivor空间的大小能够经过下面这个参数调整:

-XX:SurvivorRatio=<ratio>

<ratio>必须大于0,-XX:SurvivorRatio=<ratio>表示单个Survivor和Eden的比率。

survivor空间大小  = –Xmn/(-XX:SurvivorRatio=<ratio> + 2)

 

监控晋升阈值

-XX:MaxTenuringThreshold=n     //设置最大晋升阈值

-XX:+PrintTenuringDistribution   //打印晋升的分布或对象年龄分布到GC日志

以下面这个晋升日志:

Desired survivor size 1114112 bytes, new threshold 1 (max 6)
- age   1:    2213864 bytes,    2213864 total

Desired survivor size 1114112 bytes是Survivor空间大小 * 目标存活率(能够设定,默认50%)

new threshold 1 JVM内部计算出的晋升阈值 (max 6)设置的晋升阈值

age   1(对象年龄代)   2213864 bytes(这个年龄对象总大小),    2213864 total(全部年龄对象总大小)

Survivor目标存活率:指Minor GC后Survivor空间占用比率,若是太大,下次Minor GC后存活的对象就有可能放不下

 

从这个日志能够看出,存活对象2213864bytes大于指望Survivor大小为1124112bytes,因此对象年龄为1时,就提高到了老年代。

解决这个问题的方法就是增大Survivor空间,存活对象大小 / 目标存活率 = Survivor空间大小,本例中大概4.5M,因此修改JVM参数为:

-Xmx512m -Xms512m -Xmn50m -XX:SurvivorRatio=5

调整后的晋升日志大概以下,这个已不是上面那个应用了,因此Survivor空间不同,能说明问题就行:

Desired survivor size 87359488 bytes, new threshold 15 (max 15)
- age   1:   20701528 bytes,   20701528 total
- age   2:    4924656 bytes,   25626184 total
- age   3:    3261000 bytes,   28887184 total
- age   4:    7941120 bytes,   36828304 total

调整Survivor空间的一个重要原则:

调整Survivor空间时,应保持Eden空间不变,不然会致使Minor GC频率变小。

初始化CMS收集周期

CMS中发生的Stop-The-World压缩式垃圾收集能够在GC日志中查找并发模式失效(concurrent mode failure)定位。

若是有这个问题,就须要调整CMS收集周期。

-XX:CMSInitiatingOccupancyFraction=<percent>    //设置CMS垃圾收集周期在老年代空间占用达到多少是启动

-XX:+UseCMSInitiatingOccupancyOnly                  //告知JVM老是使用 CMSInitiatingOccupancyFraction比率启动CMS,不然只是在CMS第一次启动时

原则:CMSInitiatingOccupancyFraction设置的比率至少是老年代活跃数据的1.5倍

若是老年代空间消耗的比较慢,能够稍晚启动CMS,即将CMSInitiatingOccupancyFraction设定的更大;

若是老年代空间消耗的很快,能够将CMSInitiatingOccupancyFraction设定的更小,但不能低于活跃数据占用的比率;

下降CMS从新标记阶段占用时间

-XX:ParallelGCThreads   //控制从新标记的线程数,建议将CMS的收集线程数设置的小于默认值,不然大量GC线程会影响应用性能

-XX:+CMSScavengeBeforeRemark  //在CMS进入从新标记阶段先进行一次Minor GC,能够减小引用老年代的新生代对象数量,下降从新标记阶段的工做量

-XX:+ParallelRefProcEnabled    //使用多线程处理引用,不过在JDK6u25和6u26上有BUG

相关文章
相关标签/搜索