一些收藏

系统压测FullGC日志分析

2020-06-22  本文已影响0人  千淘萬漉

应用背景分析

压测一个业务系统,其中JVM堆内存参数如下,堆内存设置了6g,新生代3g,老年代相应的为3g,采用了CMS垃圾回收器,新生代则默认为ParNew回收器,设定触发FullGC规则为老年代使用率达到70%(默认值为75%),调低该值的目的在于降低内存碎片的影响,希望更早的触发垃圾回收。CMS垃圾回收时会采用标记清除算法,同时默认会在清除以后执行整理压缩,避免浮动垃圾与内存碎片。

 -Xms6144M -Xmx6144M -Xmn3072M -XX:+DisableExplicitGC -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:LargePageSizeInBytes=128m -XX:+UseFastAccessorMethods -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70 -XX:+PrintGCDetails -XX:+PrintGCDateStamps -verbose:gc -Xloggc:/wls/springboot/logs/gc.log -Djava.net.preferIPv4Stack=true

设定了如上的JVM参数下开始进行压测,现在分析一波基于CMS的FullGC日志。

Phase 1: Initial Mark 初始标记


该阶段会STW现象,这是CMS中两次stop-the-world事件中的一次。它有两个目标:一是标记老年代中所有的GC Roots;二是标记被年轻代中活着的对象引用的对象。

2020-04-28T16:09:39.160+0800: 1108.793: [GC (CMS Initial Mark) [1 CMS-initial-mark: 2204173K(3145728K)] 2370012K(5976896K), 0.0514097 secs] [Times
: user=0.13 sys=0.04, real=0.05 secs] 

从以上日志信息中可以提取到如下信息:

Phase 2: Concurrent Mark 并发标记


这个阶段不会STW,JVM会遍历整个老年代并且标记所有存活的对象,从“初始化标记”阶段找到的GC Roots开始。并发标记的特点是和应用程序线程同时运行,并不是老年代的所有存活对象都会被标记,因为标记的同时应用程序会改变一些对象的引用等。截取GC日志如下:

2020-04-28T16:09:39.213+0800: 1108.845: [CMS-concurrent-mark-start]
2020-04-28T16:09:39.490+0800: 1109.123: [CMS-concurrent-mark: 0.278/0.278 secs] [Times: user=1.09 sys=0.46, real=0.28 secs] 

其中,0.278/0.278 secs就是展示该阶段持续的时间和时钟时间;

Phase 3: Final Remark 重新标记


此处可以细分三个小阶段,只有第三个Final Remark阶段会有STW。

1、Concurrent Preclean

这里仍是一个回收线程并发执行阶段,和应用线程并行运行。前一个阶段在并行运行的时候,一些对象的引用已经发生了变化,当这些引用发生变化的时候,JVM会标记堆的这个区域为Dirty Card(包含被标记但是改变了的对象,被认为"dirty"),这就是 Card Marking。

2020-04-28T16:09:39.491+0800: 1109.124: [CMS-concurrent-preclean-start]
2020-04-28T16:09:39.558+0800: 1109.191: [CMS-concurrent-preclean: 0.067/0.067 secs] [Times: user=0.15 sys=0.07, real=0.07 secs] 

2、Concurrent Abortable Preclean

又一个并发阶段不会停止应用程序线程。这个阶段尝试着去承担STW的Final Remark阶段足够多的工作。这个阶段持续的时间依赖好多的因素,由于这个阶段是重复的做相同的事情直到发生aboart的条件(比如:重复的次数、多少量的工作、持续的时间等等)之一才会停止。

2020-04-28T16:09:39.559+0800: 1109.192: [CMS-concurrent-abortable-preclean-start]
2020-04-28T16:09:40.812+0800: 1110.445: [GC (Allocation Failure) 2020-04-28T16:09:40.813+0800: 1110.445: [ParNew: 2567678K->51415K(2831168K), 0.15
12751 secs] 4771852K->2259993K(5976896K), 0.1521682 secs] [Times: user=0.85 sys=0.03, real=0.16 secs] 
2020-04-28T16:09:41.753+0800: 1111.386: [CMS-concurrent-abortable-preclean: 2.030/2.194 secs] [Times: user=7.99 sys=2.63, real=2.20 secs] 

这个阶段很大程度的影响着即将来临的Final Remark的停顿

3、Final Remark

清理前做最终的标记,这个阶段是CMS中第二个并且是最后一个STW的阶段。该阶段的任务是完成标记整个年老代的所有的存活对象。由于之前的预处理是并发的,它可能跟不上应用程序改变的速度,这个时候,STW是非常需要的来完成这个严酷考验的阶段。通常CMS尽量运行Final Remark阶段在年轻代是足够干净的时候,目的是消除紧接着的连续的几个STW阶段。

2020-04-28T16:09:41.757+0800: 1111.390: [GC (CMS Final Remark) [YG occupancy: 1451165 K (2831168 K)]
2020-04-28T16:09:41.757+0800: 1111.390: [Rescan (parallel) , 0.2057074 secs]
2020-04-28T16:09:41.963+0800: 1111.595: [weak refs processing, 0.0000816 secs]
2020-04-28T16:09:41.963+0800: 1111.596: [class unloading, 0.1070335 secs]
2020-04-28T16:09:42.070+0800: 1111.703: [scrub symbol table, 0.0133941 secs]
2020-04-28T16:09:42.083+0800: 1111.716: [scrub string table, 0.0012260 secs][1 CMS-remark: 2208578K(3145728K)] 3659743K(5976896K), 0.3312628 secs] [Times: user=1.28 sys=0.01, real=0
.33 secs]

通过以上5个阶段的标记,老年代所有存活的对象已经被标记并且现在要通过Garbage Collector采用清扫的方式回收那些不能用的对象了。

Phase 4: 垃圾回收


这个阶段可以划分两个小阶段,这两个都不会STW。

1、Concurrent Sweep

这个阶段的目的就是移除那些不用的对象,回收他们占用的空间并且为将来使用。

2020-04-28T16:09:43.698+0800: 1113.331: [CMS-concurrent-sweep: 1.579/1.609 secs] [Times: user=5.35 sys=2.34, real=1.61 secs] 

2、Concurrent Reset

这个阶段并发执行,重新设置CMS算法内部的数据结构,准备下一个CMS生命周期的使用。

2020-04-28T16:09:43.699+0800: 1113.332: [CMS-concurrent-reset-start]
2020-04-28T16:09:43.707+0800: 1113.339: [CMS-concurrent-reset: 0.008/0.008 secs] [Times: user=0.03 sys=0.00, real=0.01 secs]

0.008/0.008 secs为该阶段的持续时间。

总结


总体来看,FGC的时长大约在4s,其中STW的时长为0.27+0.20+0.1+0.33=0.81s。FGC的回收时长较大,原因在于JVM堆内存的空间较大,导致在多个标记阶段耗时较长,且FGC期间因为会开启多线程进行并发回收,会出现CPU使用率上的毛刺现象,但是整体来看STW上的0.81s满足CMS一贯的低延时优点,如果在生产上内存*2的情况下,FGC和STW时长可能会线性倍增两倍。如果观察线上FGC时长过大,CPU使用率因FGC出现较多毛刺的情况下,说明CMS在应对大内存服务的回收时会显得力不从心,可以考虑采用G1回收器对JVM进行调优处理。

以下展示为CMS的完整GC日志与时间,可供大家学习参考。

2020-04-28T16:09:39.160+0800: 1108.793: [GC (CMS Initial Mark) [1 CMS-initial-mark: 2204173K(3145728K)] 2370012K(5976896K), 0.0514097 secs] [Times
: user=0.13 sys=0.04, real=0.05 secs] 

2020-04-28T16:09:39.213+0800: 1108.845: [CMS-concurrent-mark-start]
2020-04-28T16:09:39.490+0800: 1109.123: [CMS-concurrent-mark: 0.278/0.278 secs] [Times: user=1.09 sys=0.46, real=0.28 secs] 

2020-04-28T16:09:39.491+0800: 1109.124: [CMS-concurrent-preclean-start]
2020-04-28T16:09:39.558+0800: 1109.191: [CMS-concurrent-preclean: 0.067/0.067 secs] [Times: user=0.15 sys=0.07, real=0.07 secs] 

2020-04-28T16:09:39.559+0800: 1109.192: [CMS-concurrent-abortable-preclean-start]
2020-04-28T16:09:40.812+0800: 1110.445: [GC (Allocation Failure) 2020-04-28T16:09:40.813+0800: 1110.445: [ParNew: 2567678K->51415K(2831168K), 0.15
12751 secs] 4771852K->2259993K(5976896K), 0.1521682 secs] [Times: user=0.85 sys=0.03, real=0.16 secs] 
2020-04-28T16:09:41.753+0800: 1111.386: [CMS-concurrent-abortable-preclean: 2.030/2.194 secs] [Times: user=7.99 sys=2.63, real=2.20 secs] 

2020-04-28T16:09:41.757+0800: 1111.390: [GC (CMS Final Remark) [YG occupancy: 1451165 K (2831168 K)]2020-04-28T16:09:41.757+0800: 1111.390: [Resca
n (parallel) , 0.2057074 secs]2020-04-28T16:09:41.963+0800: 1111.595: [weak refs processing, 0.0000816 secs]2020-04-28T16:09:41.963+0800: 1111.596
: [class unloading, 0.1070335 secs]2020-04-28T16:09:42.070+0800: 1111.703: [scrub symbol table, 0.0133941 secs]2020-04-28T16:09:42.083+0800: 1111.
716: [scrub string table, 0.0012260 secs][1 CMS-remark: 2208578K(3145728K)] 3659743K(5976896K), 0.3312628 secs] [Times: user=1.28 sys=0.01, real=0
.33 secs] 
2020-04-28T16:09:42.089+0800: 1111.722: [CMS-concurrent-sweep-start]
2020-04-28T16:09:42.778+0800: 1112.411: [GC (Allocation Failure) 2020-04-28T16:09:42.778+0800: 1112.411: [ParNew: 2567977K->56794K(2831168K), 0.01
90506 secs] 3999542K->1491602K(5976896K), 0.0197083 secs] [Times: user=0.24 sys=0.01, real=0.02 secs] 
2020-04-28T16:09:43.698+0800: 1113.331: [CMS-concurrent-sweep: 1.579/1.609 secs] [Times: user=5.35 sys=2.34, real=1.61 secs] 
2020-04-28T16:09:43.699+0800: 1113.332: [CMS-concurrent-reset-start]
2020-04-28T16:09:43.707+0800: 1113.339: [CMS-concurrent-reset: 0.008/0.008 secs] [Times: user=0.03 sys=0.00, real=0.01 secs]
上一篇 下一篇

猜你喜欢

热点阅读