ZGC 是个啥玩意?
描述
JDK 11
加入了实验性质的ZGC
,相关JEP
见:JEP 333: ZGC: A Scalable Low-Latency Garbage Collector (Experimental)
首先我们来了解一下G1
。G1 GC
,全称Garbage-First Garbage Collector
,通过-XX:+UseG1GC
参数来启用,作为体验版随着JDK 6u14
版本面世,在JDK 7u4
版本发行时被正式推出,相信熟悉JVM
的同学们都不会对它感到陌生。在JDK 9
中,G1
被提议设置为默认垃圾收集器。见JEP 248: Make G1 the Default Garbage Collector。
但是对于一些延迟敏感的场景,
G1
还是有些不太能满足需求,比如常见的游戏,尤其是实时类的网游。
GC
性能测试
建128G
的堆,复合模式下的性能,看GC
的停顿时间。
ZGC
avg: 1.091ms (+/-0.215ms)
95th percentile: 1.380ms
99th percentile: 1.512ms
99.9th percentile: 1.663ms
99.99th percentile: 1.681ms
max: 1.681ms
G1
avg: 156.806ms (+/-71.126ms)
95th percentile: 316.672ms
99th percentile: 428.095ms
99.9th percentile: 543.846ms
99.99th percentile: 543.846ms
max: 543.846ms
结论:使用ZGC可以稳定在2ms以内!
使用指南
本文不探讨ZGC的技术实现与原理,只记录相关使用方法。
实验阶段的ZGC目前不支持Windows,以下使用方法仅在Linux经过测试。
下载JDK
下载 Linux/x64
下使用的JDK 11
快速使用
通过-XX:+UnlockExperimentalVMOptions -XX:+UseZGC
启用ZGC
java -XX:+UnlockExperimentalVMOptions -XX:+UseZGC
通过-Xmx<size>
设置最大堆大小。
ZGC是并发收集器,必须指定最大堆大小。
java -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -Xmx<size>
(可选)通过-XX:ConcGCThreads=<number>
设置并发线程数。
ZGC具有探索式的线程数自动选择功能,通常运行良好。线程数越多,GC占用CPU越多时间。线程数过少,GC可能收集的速度低于程序分配的速度。
java -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -Xmx<size> -XX:ConcGCThreads=<number>
通过-Xlog
启用GC日志记录
java -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -Xmx<size> -Xlog:gc
# 帮助 -Xlog:help
启用大页面(Huge Page
)
配置ZGC使用大页面一般会有更好的性能(吞吐量、延迟和启动时间等),并且没有明显的缺点,除了设置稍微复杂一点,配置过程通常需要root权限,所以默认情况下并未启用。
在 Linux/x86
上大页面默认大小为2MB
。
假设现在需要一个16G
的Java堆
。即需要 16G / 2M = 8192
个大页面。
因为JVM
中不仅GC
会使用Java堆
,JVM
中各种内部的数据结构也会使用,所以一般这个估计值需要偏大。在下面的示例中,将宽限2G
的大页面。(18G / 2M = 9216
)
配置系统的大页面池(需要root权限)
$ echo 9216 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
注意:如果内核找不到足够大的空闲大页面来满足需求,则无法保证上述命令成功执行。另外,内核可能需要一些时间来处理这个请求。
检查分配给池的数量,以确保请求成功并已完成。
$ cat /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
# 9216
注意:如果Linux内核 >= 4.14,则跳过下一步(安装hugetlbfs文件系统)。
ZGC需要通过hugetlbfs
文件系统访问大页面
挂载hugetlbfs
文件系统(需要root权限),并使其可供运行JVM
的用户访问。(假设此用户uid
是123)
$ mkdir /hugepages
$ mount -t hugetlbfs -o uid=123 nodev /hugepages
现在使用-XX:+UseLargePages
启用JVM
$ java -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -Xms16G -Xmx16G -XX:+UseLargePages ...
如果有多个可访问的hugetlbfs
文件系统,那么使用-XX:ZPath
指定要使用的路径。
java -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -Xms16G -Xmx16G -XX:+UseLargePages -XX:ZPath=/hugepages ...