Reference:https://time.geekbang.org/column/article/107396
GC算法
JVM提供了不同的回收算法来实现这?套回收机制,通常垃圾收集器的回收算法可以分为以下?种:
如果说收集算法是内存回收的?法论,那么垃圾收集器就是内存回收的具体实现,JDK1.7 update14 之后Hotspot虚拟机所有的回收器整理如下(以下为服务端垃圾收集器):
其实在JVM规范中并没有明确GC的运作?式,各个?商可以采?不同的?式实现垃圾收集器。我们可以通过JVM?具查询当前JVM使?的垃圾收集器类型,?先通过ps命令查询出经常ID,再通过jmap -heap ID查询出JVM的配置信息,其中就包括垃圾收集器的设置类型。
GC性能衡量指标
?个垃圾收集器在不同场景下表现出的性能也不?样,那么如何评价?个垃圾收集器的性能好坏呢?我们可以借助?些指标。
吞吐量:这?的吞吐量是指应?程序所花费的时间和系统总运?时间的?值。我们可以按照这个公式来计算GC的吞吐量:系统总运?时间=应?程序耗时+GC耗时。如果系统运?了100分钟,GC耗时1分钟,则系统吞吐量为99%。GC的吞吐量?般不能低于95%。
停顿时间:指垃圾收集器正在运?时,应?程序的暂停时间。对于串?回收器而言,停顿时间可能会?较长;而使?并发回收器,由于垃圾收集器和应?程序交替运?,程序的停顿时间就会变短,但其效率很可能不如独占垃圾收集器,系统的吞吐量也很可能会降低。
垃圾回收频率:多久发??次指垃圾回收呢?通常垃圾回收的频率越低越好,增?堆内存空间可以有效降低垃圾回收发?的频率,但同时也意味着堆积的回收对象越多,最终也会增加回收时的停顿时间。所以我们只要适当地增?堆内存空间,保证正常的垃圾回收频率即可。
GC调优策略
找出问题后,就可以进?调优了,下?介绍?种常?的GC调优策略。
1. 降低Minor GC频率
通常情况下,由于新?代空间较?,Eden区很快被填满,就会导致频繁Minor GC,因此我们可以通过增?新?代空间来降低Minor GC的频率。
可能你会有这样的疑问,扩容Eden区虽然可以减少Minor GC的次数,但不会增加单次Minor GC的时间吗?如果单次Minor GC的时间增加,那也很难达到我们期待的优化效果呀。
我们知道,单次Minor GC时间是由两部分组成:T1(扫描新?代)和T2(复制存活对象)。
假设?个对象在Eden区的存活时间为500ms,Minor GC的时间间隔是300ms,那么正常情况下,Minor GC的时间为 :T1+T2。
当我们增?新?代空间,Minor GC的时间间隔可能会扩?到600ms,此时?个存活500ms的对象就会在Eden区中被回收掉,此时就不存在复制存活对象了,所以再发?Minor GC的时间为:两次扫描新?代,即2T1。
可见,扩容后,Minor GC时增加了T1,但省去了T2的时间。通常在虚拟机中,复制对象的成本要远?于扫描成本。
如果在堆内存中存在较多的长期存活的对象,此时增加年轻代空间,反?会增加Minor GC的时间。如果堆中的短期对象很多,那么扩容新?代,单次Minor GC时间不会显著增加。因此,单次Minor GC时间更多取决于GC后存活对象的数量,??Eden区的大小
2. 降低Full GC的频率
通常情况下,由于堆内存空间不足或老年代对象太多,会触发Full GC,频繁的Full GC会带来上下?切换,增加系统的性能开销。我们可以使用哪些?法来降低Full GC的频率呢?
减少创建?对象:在平常的业务场景中,我们习惯?次性从数据库中查询出?个大对象?于web端显?。例如,我之前碰到过?个?次性查询出60个字段的业务操作,这种大对象如果超过年轻代最大对象阈值,会被直接创建在?年代;即使被创建在了年轻代,由于年轻代的内存空间有限,通过Minor GC之后也会进?到?年代。这种大对象很容易产?较多的Full GC。
我们可以将这种大对象拆解出来,首次只查询?些?较重要的字段,如果还需要其它字段辅助查看,再通过第?次查询显示剩余的字段。
增大堆内存空间:在堆内存不足的情况下,增大堆内存空间,且设置初始化堆内存为最大堆内存,也可以降低Full GC的频率。
选择合适的GC回收器
假设我们有这样?个需求,要求每次操作的响应时间必须在500ms以内。这个时候我们?般会选择响应速度较快的GC回收器,CMS(Concurrent Mark Sweep)回收器和G1回收器都是不错的选择。
而当我们的需求对系统吞吐量有要求时,就可以选择Parallel Scavenge回收器来提?系统的吞吐量。
总结
垃圾收集器的种类很多,我们可以将其分成两种类型
- 响应速度快
- 吞吐量?
通常情况下,CMS和G1回收器的响应速度快,Parallel Scavenge回收器的吞吐量?。
在JDK1.8环境下,默认使?的是Parallel Scavenge(年轻代)+ Serial Old(?年代)垃圾收集器。
通常情况,JVM是默认垃圾回收优化的,在没有性能衡量标准的前提下,尽量避免修改GC的?些性能配置参数。如果?定要改,那就必须基于?量的测试结果或线上的具体性能来进?调整。
原文地址:https://www.cnblogs.com/agilestyle/p/11488008.html