GC调优整理

jdk8 默认GC:Parallel Scavenge + Parallel Old (1.8默认)

Parallel Scavenge

新生代并行回收器,内存分布使用的复制算法。Parallel Scavenge主要关注的是应用的吞吐量,而其他收集器关注的主要是尽可能的缩短STW(stop the word)的时间。

吞度量=t1/(t1+t2)
t1运行用户代码的总时间
t2运行垃圾收集的总时间
比如,虚拟机总共运行了100分钟,其中垃圾收集花掉1分钟,那吞吐量就是99%。

Parallel Scavenge收集器提供了两个参数来用于精确控制吞吐量,一是控制最大垃圾收集停顿时间的 -XX:MaxGCPauseMillis参数,二是控制吞吐量大小的 -XX:GCTimeRatio参数
  • -XX:MaxGCPauseMillis
参数的值是一个大于0的毫秒数,收集器将尽可能的保证回收耗费的时间不超过设定的值,但是,并不是越小越好,GC停顿时间缩短是以牺牲吞吐量和新生代空间来换取的,如果设置的值太小,将会导致频繁GC,这样虽然GC停顿时间下来了,但是吞吐量也下来了。比如收集500MB时候,需要每10秒收集一次,每次回收耗时100ms;如果收集300MB的时候,需要每5秒收集一次,每次回收耗时70ms,虽然每次回收耗时更少,但是工作频次提高,导致吞吐量反而降低了。
  • -XX:GCTimeRatio
参数的值是一个大于0且小于100的整数,也就是垃圾收集时间占总时间的比率,默认值是99,就是允许最大1%(即1/(1+99))的垃圾收集时间。
Parallel Scavenge有个重要的特性,是支持GC自适应的调节策略,使用-XX:UseAdaptiveSizePolicy参数开启,开启之后,虚拟机会根据当前系统运行情况收集监控信息,动态调整新生代的比例、老年大大小等细节参数,以提供最合适的停顿时间或最大的吞吐量。开启这个参数之后,就不需要再设置新生代大小,Eden与S0/S1的比例等等参数。

 在这个改变之前,即便选择了ParallelGC,默认情况下ParallelOldGC并不会随即开启,而是要自己通过 -XX:+UseParallelOldGC 去选定。

在GC日志里,如果看到Full GC里有"ParOldGen"就是选择了ParallelOldGC

从JDK8开始,永久代(PermGen)的概念被废弃掉了,取而代之的是一个称为Metaspace的存储空间。

Linux中没找到默认GC的查看方法,而windows中会打印UseParallelGC

  •  java +XX:+PrintCommandLineFlags -version
  •  通过GC的日志来分辨

-XX:+UseAdaptiveSizePolicy:设置此选项后,并行收集器会自动调整年轻代Eden区大小和Survivor区大小的比例,以达成目标系统规定的最低响应时间或者收集频率等指标。此参数建议在使用并行收集器时,一直打开。并发收集器(响应时间优先)

G1 GC模式

G1提供了两种GC模式,Young GC和Mixed GC,两种都是完全Stop The World的。 * Young GC:选定所有年轻代里的Region。通过控制年轻代的region个数,即年轻代内存大小,来控制young GC的时间开销。 * Mixed GC:选定所有年轻代里的Region,外加根据global concurrent marking统计得出收集收益高的若干老年代Region。在用户指定的开销目标范围内尽可能选择收益高的老年代Region。

由上面的描述可知,Mixed GC不是full GC,它只能回收部分老年代的Region,如果mixed GC实在无法跟上程序分配内存的速度,导致老年代填满无法继续进行Mixed GC,就会使用serial old GC(full GC)来收集整个GC heap。所以我们可以知道,G1是不提供full GC的。

上文中,多次提到了global concurrent marking,它的执行过程类似CMS,但是不同的是,在G1 GC中,它主要是为Mixed GC提供标记服务的,并不是一次GC过程的一个必须环节。global concurrent marking的执行过程分为四个步骤: * 初始标记(initial mark,STW)。它标记了从GC Root开始直接可达的对象。 * 并发标记(Concurrent Marking)。这个阶段从GC Root开始对heap中的对象标记,标记线程与应用程序线程并行执行,并且收集各个Region的存活对象信息。 * 最终标记(Remark,STW)。标记那些在并发标记阶段发生变化的对象,将被回收。 * 清除垃圾(Cleanup)。清除空Region(没有存活对象的),加入到free list。

第一阶段initial mark是共用了Young GC的暂停,这是因为他们可以复用root scan操作,所以可以说global concurrent marking是伴随Young GC而发生的。第四阶段Cleanup只是回收了没有存活对象的Region,所以它并不需要STW。

Young GC发生的时机大家都知道,那什么时候发生Mixed GC呢?其实是由一些参数控制着的,另外也控制着哪些老年代Region会被选入CSet。 * G1HeapWastePercent:在global concurrent marking结束之后,我们可以知道old gen regions中有多少空间要被回收,在每次YGC之后和再次发生Mixed GC之前,会检查垃圾占比是否达到此参数,只有达到了,下次才会发生Mixed GC。 * G1MixedGCLiveThresholdPercent:old generation region中的存活对象的占比,只有在此参数之下,才会被选入CSet。 * G1MixedGCCountTarget:一次global concurrent marking之后,最多执行Mixed GC的次数。 * G1OldCSetRegionThresholdPercent:一次Mixed GC中能被选入CSet的最多old generation region数量。

除了以上的参数,G1 GC相关的其他主要的参数有:

参数含义
-XX:G1HeapRegionSize=n设置Region大小,并非最终值
-XX:MaxGCPauseMillis设置G1收集过程目标时间,默认值200ms,不是硬性条件
-XX:G1NewSizePercent新生代最小值,默认值5%
-XX:G1MaxNewSizePercent新生代最大值,默认值60%
-XX:ParallelGCThreadsSTW期间,并行GC线程数
-XX:ConcGCThreads=n并发标记阶段,并行执行的线程数
-XX:InitiatingHeapOccupancyPercent设置触发标记周期的 Java 堆占用率阈值。默认值是45%。这里的java堆占比指的是non_young_capacity_bytes,包括old+humongous

参考建议:

  • YGC平均耗时小于50毫秒
  • YGC执行频率不低于10秒1次
  • FGC平均耗时小于1秒
  • FGC执行频率不低于10分钟1次

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值