乐趣区

关于jvm调优:谈JVM参数GC线程数ParallelGCThreads合理性设置

作者:京东批发 刘乐

1. ParallelGCThreads 参数含意

在讲这个参数之前,先谈谈 JVM 垃圾回收 (GC) 算法的两个优化标的:吞吐量和进展时长。JVM 会应用特定的 GC 收集线程,当 GC 开始的时候,GC 线程会和业务线程抢占 CPU 工夫,吞吐量定义为 CPU 用于业务线程的工夫与 CPU 总耗费工夫的比值。为了承接更大的流量,吞吐量越大越好。

为了平安的垃圾回收,在 GC 或者 GC 某个阶段,所有业务线程都会被暂停,也就是 STW(Stop The World),STW 持续时间就是进展时长,进展时长影响响应速度,因而越小越好。

这两个优化指标是有抵触的,在肯定范畴内,参加 GC 的线程数越多,进展时长越小,但吞吐量也越小。生产实践中,须要依据业务特点设置一个正当的 GC 线程数,获得吞吐量和进展时长的均衡。

目前宽泛应用的 GC 算法,包含 PS MarkSweep/PS Scavenge, ConcurrentMarkSweep/ParNew, G1 等,都能够通过 ParallelGCThreads 参数来指定 JVM 在并行 GC 时参加垃圾收集的线程数。该值设置过小,GC 暂停工夫变长影响 RT,设置过大则影响吞吐量,从而导致 CPU 过高。

2. ParallelGCThreads 参数设置

GC 并发线程数能够通过 JVM 启动参数: -XX:ParallelGCThreads=<N> 来指定。在未明确指定的状况下,JVM 会依据逻辑核数 ncpus,采纳以下公式来计算默认值:

◦当 ncpus 小于 8 时,ParallelGCThreads = ncpus

◦否则 ParallelGCThreads = 8 + (ncpus – 8) (5/8)

一般来说,在无特殊要求下,ParallelGCThreads 参数应用默认值就能够了。然而在 JRE 版本 1.8.0_131 之前,JVM 无奈感知 Docker 的 CPU 限度,会应用宿主机的逻辑核数计算默认值。 比方部署在 128 核物理机上的容器,JVM 中默认 ParallelGCThreads 为 83,远超过了容器的核数。过多的 GC 线程数抢占了业务线程的 CPU 工夫,加上线程切换的开销,较大的升高了吞吐量。因而 JRE 1.8.0_131 之前的版本,未明确指定 ParallelGCThreads 会有较大的危险。

3. ParallelGCThreads 参数试验

创立 8C12G 容器,宿主机是 128C。模仿线上实在流量,采纳雷同 QPS,察看及比照 JVM YoungGC,JVM CPU,容器 CPU 等监控数据。场景如下:

◦场景 1: JVM ParallelGCThreads 默认值,QPS = 420,继续 5 分钟,CPU 恒定在 70%

◦场景 2: JVM ParallelGCThreads=8,QPS = 420,继续 5 分钟,CPU 恒定在 65%

◦场景 3: JVM ParallelGCThreads 默认值,QPS 刹时发压到 420,前 1min CPU 继续 100%

◦场景 4: JVM ParallelGCThreads=8,QPS 刹时发压到 420,前 2s CPU 继续 100%,前面回落

从监控数据来看,各场景下 CPU 差距较显著,特地是场景 3 和场景 4 的比照。场景 3 因为 GC 线程过多,CPU 继续 100% 时长达 1 分钟。能够得出以下两个论断:

1. 批改 ParallelGCThreads = 8 后,等同 QPS 状况下,CPU 会升高 5% 左右

2. 批改 ParallelGCThreads = 8 后,霎时发压且 CPU 打满状况下,CPU 复原较快

图 1: 容器 CPU 比照图:场景 3(上)和场景 4(下)

图 2: JVM Young GC 比照图:场景 3(上)和场景 4(下)

4. ParallelGCThreads 批改倡议

ParallelGCThreads 配置存在危险的利用,批改形式为以下两种计划(任选一种):

◦降级 JRE 版本到1.8.0_131 以上,举荐 1.8.0_192

◦在 JVM 启动参数明确指定 -XX:ParallelGCThreads=<N>,N 为下表的推荐值:

容器核数 2 4 8 16 32 64
推荐值 2 4 8 13 23 43
倡议上下界 1~2 2~4 4~8 8~16 16~32 32~64
退出移动版