垃圾回收调优
1. 调优领域
2. 确定目标
如果应用程序主要做科学运算,那么追求【高吞吐量】 如果做互联网项目 追求【低延迟】 提升用户体验 然后选择合适的回收器。 追求高吞吐量:ParallelGC 响应时间优先:CMS(jdk9不推荐,推荐G1),G1,ZGC(目标超低延迟)
当然,也可以不选择hotSpot虚拟机ahhhh
3. 最快的gc是不发生gc
数据是否太多? 数据表示是否太臃肿 对象大小、对象图?是否存在内存泄漏(向集合中不断放入对象) 策略—软引用、弱引用;缓存数据可以使用第三方缓存实现–redis 、ES,而不是直接在Java中使用map
4. 新生代调优
内存调优先从新生代开始 新生代的优化空间更大一点 新生代的特点
- 所有的 new 操作的内存分配非常廉价
TLAB thread-local allocation buffer - 死亡对象的回收代价是零
- 大部分对象用过即死
- Minor GC 的时间远远低于 Full GC
调优
-
新生代也不一定是设置地越大越好 老年代空间紧张,可能full gc了 Oracle推荐:新生代内存大于堆的25%,小于堆的50%即可 空间大了以后,一次垃圾回收所需要的时间也会增加。 -
标记、复制 复制消耗时间多,因为要移动对象在内存中的位置 -
比较理想的大小: 新生代能容纳所有【并发量*(请求 响应)】的数据 -
幸存区大到能保留【当前活跃对象+需要晋升对象】 -
晋升阈值要配置得当,让长时间存活对象能够尽快晋升
-XX:MaxTenuringThreshold=threshold 设置阈值 -XX:+PrintTenuringDistribution 打印晋升的详细信息
5. 老年代调优
以CMS为例:
- CMS的老年代内存越大越好
- 先尝试不做调优,观察一段时间。如果没有full gc,那么说明老年代内存可能是充足的,先调优新生代
- 观察发生full gc时的老年代内存占用,将老年代内存预设调大 1/4 ~ 1/3
-XX:CMSInitiatingOccupancyFraction=percent 当老年代的内存占用到达percent时,使用cms进行垃圾回收。值越低,老年代gc触发时间就越早。一般75%~80%(考虑浮动垃圾)
案例分析
- 划分更多新生代
- 重新标记的时候慢。
增加选项 -XX:CMSScavengeBeforeRemark 先将并发标记的对象做一次清理,这样重新标记的阶段扫描的对象就少了。 - 1.7版本以前永久代空间不足
|