垃圾回收调优
1.调优领域
垃圾回收只是调优的一个方向,要想使的应用程序的性能提升,要从各个方向来实现。
- 内存
- 锁竞争
- cpu占用
- io
2.确定调优目标
选择合适的调优目标
还可以尝试其他的虚拟机,比如zing 之类的。
3.最快的GC是不发生GC
从自身的程序出发,考虑是否加载了无用的数据;对象的大小是不是应该做一些瘦身优化;考虑第三方的缓存实现
4.新生代调优
- 新生代的特点
-
new一个对象时,首先会在伊甸园分配,分配速度很快
每个线程都会在伊甸园中分配一个私有的区域,即
TLAB thread-local allocation buffer 线程局部分配缓冲区,他 的作用就是让每个线程用自己私有的这块伊甸园内存来分配,这样即使多个线程同时进行对象内存分配,也是安全的。 -
死亡对象的回收代价是零。
·新生代中绝大多数的对象用过即死 -
MinorGC的时间远远低于FullGC
-
新生代越大越好吗?
幸存区设置
幸存区要足够大,大到能够保留【当前活跃对象+需要晋升对象】
如果幸存区比较小,jvm会动态的调整晋升的阈值。这样会使一些存活时间短的提前进入老年代。
但是用时我们又希望,让那些长时间存活的对象尽快晋升。(长期对象在幸存区复制来复制去浪费大量时间)
1.调整晋升阈值
2.显示晋升信息
5.老年代调优
以CMS为例
- cms的老年代内存越大越好
- 先尝试不做调优,如果发现程序运行一段时间后,没有发生fullGC,那么说明我们的老年代空间还比较充裕,无论如何都应该先从新生代开始调优。
- 如果发生了fullGC,我们要在该内存大小的基础上,将老年代内存预设调大1/4-3/4
6.案例
-
案例1 FullGC和minorGC频繁
-案例2 请求高峰期发生FullGC,单次暂停时间特别长(cms)
初始标记:仅仅标记GC Roots的直接管理对象,并且STW
CMS重新标记时会扫描整个堆内存 -
案例3 老年代充裕情况下 发生了fullGC(cms jdk1.7)
jdk1.7是使用永久代的,1.8后使用元空间,是使用操作系统的空间的,所以内存充足。
所以是永久代空间不足,可以增加永久代和初始值和最大值。