ZGC

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

垃圾收集器,也被称为 ZGC,是一个可扩展的低延迟垃圾收集器,旨在实现以下目标:

  • Sub-millisecond 亚毫秒 max pause times 最大暂停时间
  • Pause times 暂停时间do not 不要 increase with the heap, live-set or root-set size 随着堆、活集或根集大小的增加而增加
  • Handle heaps ranging from a 处理堆的范围从8MB to 16TB 16 TB in size 大小

ZGC was initially introduced as an experimental feature in JDK 11, and was declared Production Ready in JDK 15.

ZGC 最初是作为 JDK 11中的一个实验性特性引入的,在 JDK 15中被声明为 Production Ready。

At a glance, ZGC is:

乍一看,ZGC 是:

  • Concurrent 同时进行
  • Region-based 以区域为基础
  • Compacting 压缩
  • NUMA-aware 支持 numa 的
  • 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.

ZGC 的核心是一个并发垃圾收集器,这意味着所有繁重的提升工作都在 Java 线程继续执行时完成。这极大地限制了垃圾收集对应用程序响应时间的影响。

 

 

Supported Platforms

支持平台

Platform 平台
Supported 支持
Since 自从
Comment 评论
Linux/x64 (tick) JDK 15 (Experimental since JDK 11) JDK 15(从 JDK 11开始的实验)  
Linux/AArch64 (tick) JDK 15 (Experimental since JDK 13) JDK 15(从 JDK 13开始的实验)  
Linux/PPC (tick) JDK 17  
macOS/x64 (tick) JDK 15 (Experimental since JDK 14) JDK 15(从 JDK 14开始的实验)  
macOS/AArch64 (tick) JDK 17  
Windows/x64 (tick) JDK 15 (Experimental since JDK 14) JDK 15(从 JDK 14开始的实验) Requires Windows version 1803 (Windows 10 or Windows Server 2019) or later. 需要 Windows 版本1803(Windows 10或 Windows Server 2019)或更高版本
Windows/AArch64 (tick) JDK 16  

Quick Start

快速开始

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

如果您是第一次尝试 ZGC,可以使用以下 GC 选项开始:

-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:

下面的 JVM 选项可以与 ZGC 一起使用:

General GC Options 一般 GC 选项
ZGC Options ZGC 选项
ZGC Diagnostic Options (-XX:+UnlockDiagnosticVMOptions) ZGC 诊断选项(- XX: + UnlockDiagnosticVMOptions)
-XX:MinHeapSize, -Xms
-XX:InitialHeapSize, -Xms
-XX:MaxHeapSize, -Xmx
-XX:SoftMaxHeapSize
-XX:ConcGCThreads
-XX:ParallelGCThreads
-XX:UseDynamicNumberOfGCThreads
-XX:UseLargePages
-XX:UseTransparentHugePages
-XX:UseNUMA
-XX:SoftRefLRUPolicyMSPerMB
-XX:AllocateHeapAt

-XX:ZAllocationSpikeTolerance

- XX: 区域分布/峰值容忍度

-XX:ZCollectionInterval

- XX: ZCollectionInterval

-XX:ZFragmentationLimit

- XX: ZFragmentationLimit

-XX:ZMarkStackSpaceLimit

- XX: ZMarkStackSpaceLimit

-XX:ZProactive

- XX: ZProactive

-XX:ZUncommit

- XX: ZUncommit

-XX:ZUncommitDelay

- XX: ZUncommitDelay

-XX:ZStatisticsInterval

- XX: zstatistical_report/interval

-XX:ZVerifyForwarding

- XX: ZVerifyForwarding

-XX:ZVerifyMarking

- XX: ZVerifyMarking

-XX:ZVerifyObjects

- XX: ZVerifyObjects

-XX:ZVerifyRoots

- XX: ZVerifyRoots

-XX:ZVerifyViews

- XX: ZVerifyViews

Enabling ZGC

启用 ZGC

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

使用-XX: + UseZGC 选项启用 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.

ZGC 最重要的调优选项是设置最大堆大小(- Xmx < size >)。由于 ZGC 是一个并发收集器,因此必须选择最大堆大小,以便: 1)堆可以容纳应用程序的活动集,2)堆中有足够的净空,允许在 GC 运行时对分配进行服务。需要多少净空空间很大程度上取决于分配率和应用程序的活动设置大小。一般来说,给 ZGC 的内存越多越好。但与此同时,浪费内存是不可取的,因此关键在于找到内存使用和 GC 运行频率之间的平衡点。

Setting Concurrent GC Threads

设置并发 GC 线程

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.

可能需要考虑的第二个调优选项是设置并发 GC 线程的数量(- XX: concthreads = < number >)。ZGC 有启发式自动选择这个数字。这种启发式方法通常工作得很好,但是根据应用程序的特性,可能需要对其进行调整。这个选项实际上决定了应该给 GC 多少 cpu 时间。如果使用太多,GC 将从应用程序中占用太多 cpu 时间。如果给它太少,应用程序分配垃圾的速度可能会超过 GC 收集垃圾的速度。

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.

注意!一般来说,如果低延迟(即低应用程序响应时间)对您的应用程序很重要,那么就不要过度供应您的系统。理想情况下,您的系统的 CPU 利用率不应该超过70% 。

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).

默认情况下,ZGC 取消未使用的内存,并将其返回到操作系统。这对于关注内存占用的应用程序和环境非常有用。可以使用-XX:-ZUncommit 禁用此特性。此外,内存将不会被取消,因此堆大小会缩小到最小堆大小(- Xms)以下。这意味着,如果将最小堆大小(- Xms)配置为等于最大堆大小(- 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.

可以使用-XX: ZUncommitDelay = < seconds > (默认为300秒)配置 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).

注意!在 Linux 上,卸载未使用的内存需要 fallocate (2)和 fallocate _ fl _ punch _ hole 支持,这两个支持首次出现在内核版本3.5(针对 tmpfs)和4.3(针对 hugetlbfs)中。

Enabling Large Pages On Linux

在 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.

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

On Linux/x86, large pages (also known as "huge pages") have a size of 2MB.

在 Linux/x86上,大页面(也称为“巨大页面”)的大小为2 MB。

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

假设您需要一个16g 的 Java 堆,这意味着您需要16g/2M = 8192个大页面。

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):

配置系统的巨大页面池,使其具有所需的数字页面(需要 root 权限) :

$ 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, 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.

注意!如果您使用的是 Linux 内核 > = 4.14,那么可以跳过下一步(安装 hugetlbfs 文件系统)。但是,如果您使用的是旧内核,那么 ZGC 需要通过 hugetlbfs 文件系统访问大页面。

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).

挂载一个 hugetlbfs 文件系统(需要 root 权限) ,并让运行 JVM 的用户可以访问它(在本例中,我们假设这个用户有123作为 uid)。

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

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

现在使用-XX: + UseLargePages 选项启动 JVM。

$ 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.

如果有多个可访问的 hugetlbfs 文件系统可用,那么(只有在这种情况下)还必须使用-XX: AllocateHeapAt 来指定要使用的文件系统的路径。例如,假设安装了多个可访问的 hugetlbfs 文件系统,但是您特别希望将其安装在/hugepages 上的文件系统,那么请使用以下选项。

$ 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.

注意!巨大的页面池的配置和 hugetlbfs 文件系统的挂载在重新引导时不会持久,除非采取了适当的措施。

Enabling Transparent Huge Pages On Linux

在 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.

注意! 在 Linux 上,使用带有透明巨大页面的 ZGC 需要内核 > = 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.

这些选项告诉 JVM 发出 madvise (... ,madv_hugepage)调用来消除内存中的应用程序,这对于在 madvise 模式下使用透明的巨大页面非常有用。

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

要启用透明的巨大页面,您还需要通过启用 madvise 模式来配置内核。

$ 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

启用 NUMA 支持

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 only use memory on a single NUMA node. 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.

ZGC 具有 NUMA 支持,这意味着它将尽最大努力将 Java 堆分配直接导向 NUMA 本地内存。这个特性是默认启用的。但是,如果 JVM 检测到它只能在单个 NUMA 节点上使用内存,那么它将自动禁用。一般来说,您不需要担心这个设置,但是如果您想显式地覆盖 JVM 的决策,您可以使用-XX: + UseNUMA 或-XX:-UseNUMA 选项来实现。

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

在 NUMA 机器上运行时(例如,多套接字 x86机器) ,启用 NUMA 支持通常会带来显著的性能提升。

Enabling GC Logging

启用 GC 日志记录

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

使用以下命令行选项启用 GC 日志记录:

-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):

要启用基本日志记录(每个 GC 只有一行输出) :

-Xlog:gc:gc.log

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

要启用对调优/性能分析有用的 GC 日志记录:

-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.

其中 gc * 表示记录包含 gc 标记的所有标记组合,而: gc.log 表示将日志写入名为 gc.log 的文件。

Change Log

更改日志

JDK 17

  • Dynamic Number of GC threads GC 线程的动态数量
  • Reduced mark stack memory usage 减少标记堆栈内存使用
  • macOS/aarch64 support macOS/aarch64支持
  • GarbageCollectorMXBeans for both pauses and cycles 用于暂停和循环的 garbagecolletormxbeans
  • Fast JVM termination 快速 JVM 终止

JDK 16

  • Concurrent Thread Stack Scanning ( 并发线程堆栈扫描(JEP 376 376)
  • Support for in-place relocation 支持就地搬迁
  • Performance improvements (allocation/initialization of forwarding tables, etc) 性能改进(分配/初始化转发表等)

JDK 15

  • Production ready ( 生产准备就绪(JEP 377 377)
  • Improved NUMA awareness 提高 NUMA 意识
  • Improved allocation concurrency 改进的分配并发性
  • Support for Class Data Sharing (CDS) 支持类数据共享(CDS)
  • Support for placing the heap on NVRAM 支持将堆放在 NVRAM 上
  • Support for compressed class pointers 支持压缩类指针
  • Support for incremental uncommit 支持增量取消提交
  • Fixed support for transparent huge pages 修正了对透明巨大页面的支持
  • Additional JFR events 其他 JFR 事件

JDK 14

  • macOS support ( macOS 支持(JEP 364 364)
  • Windows support ( Windows 支持(JEP 365 365)
  • Support for tiny/small heaps (down to 8M) 支持微小/小堆(下降到8m)
  • Support for JFR leak profiler 支持 JFR 泄漏分析器
  • Support for limited and discontiguous address space 支持有限和不连续的地址空间
  • Parallel pre-touch (when using -XX:+AlwaysPreTouch) 并行预触摸(使用 -XX: + AlwaysPreTouch 时)
  • Performance improvements (clone intrinsic, etc) 性能改进(克隆内在等)
  • Stability improvements 稳定性的提高

JDK 13

  • Increased max heap size from 4TB to 16TB 最大堆大小从4tb 增加到16tb
  • Support for uncommitting unused memory ( 支持卸载未使用的内存(JEP 351 351)
  • Support for -XX:SoftMaxHeapSIze 支持 -XX: SoftMaxHeapSIze
  • Support for the Linux/AArch64 platform 对 Linux/aarch64平台的支持
  • Reduced Time-To-Safepoint 缩短到安全点的时间

JDK 12

  • Support for concurrent class unloading 支持并发类卸载
  • Further pause time reductions 进一步的暂停时间减少

JDK 11

  • Initial version of ZGC ZGC 的初始版本
  • Does not support class unloading (using -XX:+ClassUnloading has no effect) 不支持类卸载(使用-XX: + class卸载没有效果)

FAQ

常见问题

What does the "Z" in ZGC stand for?

ZGC 中的“ z”代表什么?

It doesn't stand for anything, ZGC is just a name. It was originally inspired by, or a homage to, ZFS (the filesystem) which in many ways was revolutionary when it first came out. Originally, ZFS was an acronym for "Zettabyte File System", but that meaning was abandoned and it was later said to not stand for anything. It's just a name. See Jeff Bonwick's Blog for more details.

它不代表任何东西,ZGC 只是一个名字。它最初是受到 ZFS (文件系统)的启发,或者说是对它的一种敬意,在它第一次出现的时候,在很多方面都是革命性的。起初,ZFS 是“ Zettabyte File System”的首字母缩写,但这个意思被抛弃了,后来人们说它不代表任何东西。只是个名字而已。更多详情请参见 Jeff Bonwick 的博客。

—————————————————————

翻译原文:https://wiki.openjdk.java.net/display/zgc 

posted @ 2022-01-26 20:00  yuing_cc  阅读(746)  评论(0)    收藏  举报