1. 程式人生 > 程式設計 >ZGC(Z Garbage Collector)完全指南

ZGC(Z Garbage Collector)完全指南

ZGC是從JDK11中引入的一種新的支援彈性伸縮低延遲垃圾收集器,ZGC可以工作在KB~TB的記憶體之下,作為一種併發的垃圾收集器,ZGC保證應用延遲不會超過10毫秒(即便在堆記憶體很大的情況下),在JDK11中是以實驗階段的特性被髮布出來的,到JDK13時,ZGC可以支援到16TB的堆記憶體,並且可以將未提交的記憶體歸還給作業系統

為什麼引入ZGC

JVM的自動垃圾收集雖然減少了開發人員的工作,在一定程度上減少了記憶體洩漏的風險,但是由於GC是自動進行的,一些無法預知的事情有時候可能產生對應用有害的影響。

  • 延遲增加導致應用的吞吐量和效能

隨著時代發展,硬體會逐漸便宜,應用使用的記憶體將會越來越大,但是又不能增加延遲,降低吞吐量

ZGC保證,不管在什麼情況下,延遲不會超過10毫秒。

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

  • Pause times do not exceed 10ms
  • Pause times do not increase with the heap or live-set size
  • Handle heaps ranging from a few hundred megabytes to multi terabytes
    in size

ZGC特性

ZGC最典型的特性是它是一款併發(concurrent)的GC,其它的特性如下:

  • 它可以標記記憶體,複製和遷移(relocate)記憶體,所有的操作都是併發的,同時它有一個併發的引用處理器
  • 其它的垃圾收集器都是使用store barriers,ZGC使用load barriers,用於跟蹤記憶體
    • lock->unlock->read->load 讀記憶體
    • use->assign->store->write 寫記憶體
  • ZGC可以更加靈活的配置大小和策略,相比於G1,它可以更好的處理非常大(very large)物件的釋放
  • ZGC只有一代,沒有新生代,老年代什麼的,但是ZGC可以支援區域性壓縮,在記憶體恢復和遷移(reclaim and relocate)時,ZGC仍然有很高的效能
  • ZGC依賴NUMA-aware(非均衡儲存器訪問),需要我們的記憶體支援這種特點

特性進度表

  • JDK11,2018年 9月
    • ZGC釋出
    • 不支援類的解除安裝。-XX:+ClassUnloading 不生效
  • JDK12 2019年 3月
    • 支援併發的類解除安裝
    • 暫停時間進一步縮短
  • JDK13 2019年 9月
    • 最大堆記憶體從4TB -> 16TB
    • 支援歸還未使用的記憶體 uncommitting unused memory
    • 支援Linux與/AArch64平臺
    • 減少時間到一個固定的時間點之下 (Reduced Time-To-Safepoint)
    • 支援 -XX:SoftMaxHeapSize ,當設定這個引數的時候,ZGC會盡量在指定的記憶體大小之下,除非為了避免記憶體溢位:參考:bugs.openjdk.java.net/browse/JDK-…
  • JDK 14 計劃在2020年3月
    • 增加穩定性
    • 支援不連續的地址空間
    • ...

ZGC支援的平臺:

平臺 是否支援 當前進度
Linux/x64 Y Since JDK 11
Linux/AArch64 Y Since JDK 13
macOS In Progress
Windows In Progress

垃圾收集原理

幾個術語:

  • parallel 多個垃圾收集執行緒在一起工作,應用可能會停止
  • serial 垃圾收集器只有一個執行緒在工作
  • stop the world 應用程式停止
  • concurrent 垃圾收集器在後臺執行,應用程式同時也在執行
  • incremental 在垃圾收集工作結束之前,先停止垃圾收集,等一會再過來完成剩下的工作

ZGC引入了兩個新的概念,pointer coloringload barriers.

Point Coloring

這個特性讓ZGC能夠發現,標記,定位和重新對映物件,它只能工作在64位的作業系統上,實現colored pointer需要虛擬地址(virtual address masking)。

image-20191107074011335

  • finalizable 物件可以被finalizer到達
  • marked0 和marked1 標記可達的物件
  • remap 引用指標到當前物件的地址,物件可能會被relocate,這個地址表示物件被relocate

Load Barrier

load barrier是一段程式碼,當執行緒從堆中載入引用的時候被執行。例如,當我們訪問物件的一個非主要型別的屬性。

在ZGC中,load barrier檢查引用的元資料位,根據元資料位對引用的物件做一些處理,因此可能在我們獲取物件的時候物件的引用會被修改掉,但是不影響我們的使用。

實戰

可以從jdk官網下載最新版本的JDK,下載地址:

www.oracle.com/technetwork…

快速開始

GC日誌標記格式如下:

-Xlog:<tag set>,[<tag set>,...]:<log file>
複製程式碼

只是想要檢視ZGC是否生效:

-XX:+UnlockExperimentalVMOptions -XX:+UseZGC -Xmx<size> -Xlog:gc
複製程式碼

想要檢視更加詳細的ZGC日誌資訊:

-XX:+UnlockExperimentalVMOptions -XX:+UseZGC -Xmx<size> -Xlog:gc*
複製程式碼

將更詳細的日誌資訊記錄在檔案中:

-XX:+UnlockExperimentalVMOptions -XX:+UseZGC -Xmx<size> -Xlog:gc*:gc.log
複製程式碼

img

GC調參

通用GC選項 ZGC選項 ZGC 診斷選項-XX:+UnlockDiagnosticVMOptions
-XX:MinHeapSize,-Xms -XX:InitialHeapSize,-Xms -XX:MaxHeapSize,-Xmx -XX:SoftMaxHeapSize -XX:SoftRefLRUPolicyMSPerMB -XX:ZAllocationSpikeTolerance -XX:ZCollectionInterval -XX:ZFragmentationLimit -XX:ZMarkStackSpaceLimit -XX:ZPath -XX:ZUncommit -XX:ZUncommitDelay -XX:ZProactive -XX:ZStatisticsInterval -XX:ZVerifyForwarding -XX:ZVerifyMarking -XX:ZVerifyObjects -XX:ZVerifyRoots -XX:ZVerifyViews

是否啟用NUMA支援:

# 啟用NUMA
-XX:+UseNUMA 

# 停用NUMA
-XX:-UseNUMA 
複製程式碼

調整併發的執行緒數:

-XX:ConcGCThreads=
複製程式碼

返回未提交的記憶體到作業系統,堆記憶體不會地址設定的最小堆記憶體-Xms

# 多久未提交的記憶體會返回給系統
-XX:+ZUncommit  -XX:ZUncommitDelay=<seconds>
複製程式碼

開啟大分頁,一般會帶來更好的效能提升,吞吐量,延遲和啟動時間都有所改善。並沒有看到明顯的缺點

  • 大分頁在Linux系統中一般為2MB的大小,如果有16G的堆記憶體,那麼意味著需要16GB/2MB = 8192個大分頁,以下命令需要 Linux kernel >= 4.14
# 配置作業系統中的分頁池數量
echo 9216 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages

# 檢視系統中現在的分頁數量
cat /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages


-XX:+UseLargePages
複製程式碼
  • 如果Linux kernel < 4.14,那麼如下方式
mkdir /hugepages
mount -t hugetlbfs -o uid=123 nodev /hugepages 
java -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -Xms16G -Xmx16G -XX:+UseLargePages
複製程式碼

開啟透明分頁,透明分頁可能導致延遲上的一些問題,有時候不推薦使用,開啟透明分頁需要Linux kernel < 4.7

# 開啟透明分頁
echo madvise > /sys/kernel/mm/transparent_hugepage/enabled
echo advise > /sys/kernel/mm/transparent_hugepage/shmem_enabled


-XX:+UseTransparentHugePage
複製程式碼

最後

ZGC仍然是處於試驗特性階段,但其保證延遲時間不低於10ms的特性,以及當前對堆記憶體大小的支援力度,還是值得一試,讓我們期待ZGC成為一款更加優越的垃圾收集器吧。

參考