【ZGC】G1停顿40ms很不错了?NO ZGC 10ms内! 厉害

本文详细介绍了如何在CentOS8.1环境下配置和使用OpenJDK11的ZGC(Z Garbage Collector),包括安装、设置环境变量、启用大页面和调整JVM参数。实验结果显示,ZGC的停顿时间极短,适合低延迟需求的应用。文章还对比了G1垃圾收集器,突显ZGC的优越性能,并提供了详细的配置和调优指南。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 系统环境

os centos 8.1, jvm jdk hotspot 11, kernel (yum info kernel -q) Version : 4.18.0  

2 最终配置流程:

  A:openjdk 11 install 

     sudo yum install java-11-openjdk-devel

     sudo alternatives --config java

  B: 设置环境变量

     cat > /etc/profile.d/java11.sh

     export JAVA_HOME=\$(dirname \$(dirname \$(readlink \$(readlink \$(which javac)))))

     export PATH=\$PATH:\$JAVA_HOME/bin

     export CLASSPATH=.:\$JAVA_HOME/jre/lib:\$JAVA_HOME/lib:\$JAVA_HOME/lib/tools.jar

     EOF

     source /etc/profile.d/java11.sh   

  C: Enabling Large Pages On Linux 分配内存大页池 根据jvm实际使用的堆内存进行分配,如 6G 6*1024/2M=3072 

     echo 3072 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages

     cat /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages    

  D: jvm 启动参数 (6g内存)

     -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -Xmx6g -Xms6g  -XX:+UseLargePages -XX:+UseNUMA -Xlog:safepoint,classhisto*=trace,age*,gc*=info:file=/root/${APP_NAME}/logs/gc-%t.log:time,tid,tags:filecount=5,filesize=50m 

3 线上效果对比:

     G1:  

          [Times: user=0.14 sys=0.02, real=0.04 secs]  #40ms

     ZGC:  

          [gc,phases   ] GC(350) Pause Mark Start 4.666ms

          [gc,phases   ] GC(350) Pause Mark End 0.481ms

          [gc,phases   ] GC(350) Pause Relocate Start 4.665ms  #总共9.8ms+

4 小结

  ZGC 作为下一代垃圾回收器,性能非常优秀。ZGC 垃圾回收过程几乎全部是并发,实际 STW 停顿时间极短,不到 10ms。这得益于其采用的着色指针和读屏障技术。          

5 参考

  https://wiki.openjdk.java.net/display/zgc/Main

6 附录  

附录1 ZGC Quick Start

The Z Garbage Collector, also known as ZGC, is a scalable low latency garbage collector designed to meet the following goals:

  • Max pause times of a few milliseconds (*)

  • Pause times do not increase with the heap or live-set size (*)
  • Handle heaps ranging from a 8MB to 16TB in size

At a glance, ZGC is:

  • Concurrent
  • Region-based
  • Compacting
  • NUMA-aware
  • Using colored pointers
  • Using load barriers

At its core, ZGC is a concurrent garbage collector, meaning all heavy lifting work is done while Java threads continue to execute. This greatly limits the impact garbage collection will have on your application's response time.

This OpenJDK project is sponsored by the HotSpot Group.


*) Work is ongoing, which will make ZGC a sub-millisecond max pause time GC, where pause times do not increase with heap, live-set, or root-set size.

Contents

 

 

Supported Platforms

Platform

Supported

Since

Comment

Linux/x641JDK 11 
Linux/AArch641JDK 13 
macOS1JDK 14 
Windows1JDK 14Requires Windows version 1803 (Windows 10 or Windows Server 2019) or later.

Quick Start

If you're trying out ZGC for the first time, start by using the following GC options:

-XX:+UseZGC -Xmx<size> -Xlog:gc

For more detailed logging, use the following options:

-XX:+UseZGC -Xmx<size> -Xlog:gc*

See below for more information on these and additional options.

Configuration & Tuning

Overview

The following JVM options can be used with ZGC:

General GC Options

ZGC Options

ZGC Diagnostic Options (-XX:+UnlockDiagnosticVMOptions)

-XX:MinHeapSize, -Xms

-XX:InitialHeapSize, -Xms

-XX:MaxHeapSize, -Xmx

-XX:SoftMaxHeapSize

-XX:ConcGCThreads

-XX:ParallelGCThreads

-XX:UseLargePages

-XX:UseTransparentHugePages

-XX:UseNUMA

-XX:SoftRefLRUPolicyMSPerMB

-XX:AllocateHeapAt

-XX:ZAllocationSpikeTolerance

-XX:ZCollectionInterval

-XX:ZFragmentationLimit

-XX:ZMarkStackSpaceLimit

-XX:ZProactive

-XX:ZUncommit

-XX:ZUncommitDelay

-XX:ZStatisticsInterval

-XX:ZVerifyForwarding

-XX:ZVerifyMarking

-XX:ZVerifyObjects

-XX:ZVerifyRoots

-XX:ZVerifyViews

Enabling ZGC

Use the -XX:+UseZGC options to enable ZGC.

Setting Heap Size

The most important tuning option for ZGC is setting the max heap size (-Xmx<size>). Since ZGC is a concurrent collector a max heap size must be selected such that, 1) the heap can accommodate the live-set of your application, and 2) there is enough headroom in the heap to allow allocations to be serviced while the GC is running. How much headroom is needed very much depends on the allocation rate and the live-set size of the application. In general, the more memory you give to ZGC the better. But at the same time, wasting memory is undesirable, so it’s all about finding a balance between memory usage and how often the GC needs to run.

Setting Concurrent GC Threads

The second tuning option one might want to look at is setting the number of concurrent GC threads (-XX:ConcGCThreads=<number>). ZGC has heuristics to automatically select this number. This heuristic usually works well but depending on the characteristics of the application this might need to be adjusted. This option essentially dictates how much CPU-time the GC should be given. Give it too much and the GC will steal too much CPU-time from the application. Give it too little, and the application might allocate garbage faster than the GC can collect it.

NOTE! In general, if low latency (i.e. low application response time) is important for you application, then never over-provision your system. Ideally, your system should never have more than 70% CPU utilization.

Returning Unused Memory to the Operating System

By default, ZGC uncommits unused memory, returning it to the operating system. This is useful for applications and environments where memory footprint is a concern. This feature can be disabled using -XX:-ZUncommit. Furthermore, memory will not be uncommitted so that the heap size shrinks below the minimum heap size (-Xms). This means this feature will be implicitly disabled if the minimum heap size (-Xms) is configured to be equal to the maximum heap size (-Xmx).

An uncommit delay can be configured using -XX:ZUncommitDelay=<seconds> (default is 300 seconds). This delay specifies for how long memory should have been unused before it's eligible for uncommit.

NOTE! On Linux, uncommitting unused memory requires fallocate(2) with FALLOC_FL_PUNCH_HOLE support, which first appeared in kernel version 3.5 (for tmpfs) and 4.3 (for hugetlbfs).

Enabling Large Pages On Linux

Configuring ZGC to use large pages will generally yield better performance (in terms of throughput, latency and start up time) and comes with no real disadvantage, except that it's slightly more complicated to setup. The setup process typically requires root privileges, which is why it's not enabled by default.
On Linux/x86, large pages (also known as "huge pages") have a size of 2MB.

将ZGC配置为使用大页面通常会产生更好的性能(在吞吐量,延迟和启动时间方面),并且没有真正的缺点,除了设置稍微复杂些。设置过程通常需要root特权,这就是默认情况下未启用它的原因。
在Linux / x86上,大页面(也称为“大页面”)的大小为2MB

Let's assume you want a 16G Java heap. That means you need 16G / 2M = 8192 huge pages.

First assign at least 16G (8192 pages) of memory to the pool of huge pages. The "at least" part is important, since enabling the use of large pages in the JVM means that not only the GC will try to use these for the Java heap, but also that other parts of the JVM will try to use them for various internal data structures (code heap, marking bitmaps, etc). In this example we will therefore reserve 9216 pages (18G) to allow for 2G of non-Java heap allocations to use large pages.//

首先,将至少16G(8192页)的内存分配给大页池。 “至少”部分很重要,因为在JVM中启用大页面的使用意味着不仅GC将尝试将这些页面用于Java堆,而且JVM的其他部分还将尝试将其用于各种操作。内部数据结构(代码堆,标记位图等)。因此,在此示例中,我们将保留9216页(18G),以允许2G的非Java堆分配使用大页。

Configure the system's huge page pool to have the required number pages (requires root privileges):

$ echo 9216 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages

Note that the above command is not guaranteed to be successful if the kernel can not find enough free huge pages to satisfy the request. Also note that it might take some time for the kernel to process the request. Before proceeding, check the number of huge pages assigned to the pool to make sure the request was successful and has completed.

$ cat /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages

9216 

NOTE! If you're using a Linux kernel >= 4.14, (uname -r 或者 yum info kernel -q 查看kernal 版本)then the next step (where you mount a hugetlbfs filesystem) can be skipped. However, if you're using an older kernel then ZGC needs to access large pages through a hugetlbfs filesystem.Mount a hugetlbfs filesystem (requires root privileges) and make it accessible to the user running the JVM (in this example we're assuming this user has 123 as its uid).

$ mkdir /hugepages

$ mount -t hugetlbfs -o uid=123 nodev /hugepages 

Now start the JVM using the -XX:+UseLargePages option.

$ java -XX:+UseZGC -Xms16G -Xmx16G -XX:+UseLargePages ...

If there are more than one accessible hugetlbfs filesystem available, then (and only then) do you also have to use -XX:AllocateHeapAt to specify the path to the filesystems you want to use. For example, assume there are multiple accessible hugetlbfs filesystems mounted, but the filesystem you specifically want to use it mounted on /hugepages, then use the following options.

$ java -XX:+UseZGC -Xms16G -Xmx16G -XX:+UseLargePages -XX:AllocateHeapAt=/hugepages ...

NOTE! The configuration of the huge page pool and the mounting of the hugetlbfs file system is not persistent across reboots, unless adequate measures are taken.

Enabling Transparent Huge Pages On Linux

An alternative to using explicit large pages (as described above) is to use transparent huge pages. Use of transparent huge pages is usually not recommended for latency sensitive applications, because it tends to cause unwanted latency spikes. However, it might be worth experimenting with to see if/how your workload is affected by it. But be aware, your mileage may vary.

NOTE! On Linux, using ZGC with transparent huge pages enabled requires kernel >= 4.7.

Use the following options to enable transparent huge pages in the VM:

-XX:+UseLargePages -XX:+UseTransparentHugePages

These options tell the JVM to issue madvise(..., MADV_HUGEPAGE) calls for memory it mapps, which is useful when using transparent huge pages in madvise mode.

To enable transparent huge pages you also need to configure the kernel, by enabling the madvise mode.

$ echo madvise > /sys/kernel/mm/transparent_hugepage/enabled

and

$ echo advise > /sys/kernel/mm/transparent_hugepage/shmem_enabled

See the kernel documentation for more information.

Enabling NUMA Support

ZGC has NUMA support, which means it will try it's best to direct Java heap allocations to NUMA-local memory. This feature is enabled by default. However, it will automatically be disabled if the JVM detects that it's bound to a sub-set of the CPUs in the system. In general, you don't need to worry about this setting, but if you want to explicitly override the JVM's decision you can do so by using the -XX:+UseNUMA or -XX:-UseNUMA options.

When running on a NUMA machine (e.g. a multi-socket x86 machine), having NUMA support enabled will often give a noticeable performance boost.

Enabling GC Logging

GC logging is enabled using the following command-line option:

-Xlog:<tag set>,[<tag set>, ...]:<log file>

For general information/help on this option:

-Xlog:help

To enable basic logging (one line of output per GC):

-Xlog:gc:gc.log

To enable GC logging that is useful for tuning/performance analysis:

-Xlog:gc*:gc.log

Where gc* means log all tag combinations that contain the gc tag, and :gc.log means write the log to a file named gc.log.

附录 2 

 

jdk 8 install
sudo dnf install java-1.8.0-openjdk-devel

jdk 11 install   
sudo yum install java-11-openjdk-devel
如果多个版本: 
sudo alternatives --config java
sudo alternatives --list

// 版本查看
$ java -version
openjdk 11-ea 2018-09-25
OpenJDK Runtime Environment (build 11-ea+28)
OpenJDK 64-Bit Server VM (build 11-ea+28, mixed mode, sharing)
$ which java
/usr/bin/java

// 确认java安装目录
echo $(dirname $(dirname $(readlink $(readlink $(which javac)))))


//  设置环境变量
cat > /etc/profile.d/java11.sh <<EOF
export JAVA_HOME=\$(dirname \$(dirname \$(readlink \$(readlink \$(which javac)))))
export PATH=\$PATH:\$JAVA_HOME/bin
export CLASSPATH=.:\$JAVA_HOME/jre/lib:\$JAVA_HOME/lib:\$JAVA_HOME/lib/tools.jar
EOF

source /etc/profile.d/java11.sh

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

自驱

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值