Jdk11,Jdk12的低延迟垃圾收集器ZGC
https://wiki.openjdk.java.net/display/zgc/Main
Z垃圾收集器,也稱為ZGC,是一種可擴展的低延遲垃圾收集器,旨在實現以下目標:
- 暫停時間不超過10毫秒
- 暫停時間不會隨堆或實時設置大小而增加
- 處理堆范圍從幾百M到幾T字節大小
一目了然,ZGC是:
- 同時
- 基于區域的
- 壓實
- NUMA感知
- 使用彩色指針
- 使用負載障礙
ZGC的核心是并發垃圾收集器,這意味著所有繁重的工作都在Java線程繼續執行時完成。這極大地限制了垃圾收集對應用程序響應時間的影響。
這個OpenJDK項目由HotSpot Group贊助。
?
JDK 11
- ZGC的初始版本
- 不支持類卸載(使用-XX:+ ClassUnloading沒有效果)
JDK 12
- 進一步暫停時間縮短
- 增加了對類卸載的支持
JVM選項
啟用ZGC
使用-XX:+UnlockExperimentalVMOptions -XX:+UseZGC選項啟用ZGC。
設置堆大小
ZGC最重要的調整選項是設置最大堆大小(-Xmx<size>)。由于ZGC是并發收集器,因此必須選擇最大堆大小,以便:1)堆可以容納應用程序的實時集,以及2)堆中有足夠的空間允許在GC處理時分配服務運行。需要多少空間取決于應用程序的分配率和實時設置大小。一般來說,你給ZGC的內存越多越好。但與此同時,浪費內存是不可取的,因此所有關于在內存使用和GC運行頻率之間找到平衡點。
設置并發GC線程
可能要查看的第二個調優選項是設置并發GC線程數(-XX:ConcGCThreads=<number>)。ZGC具有自動選擇此編號的啟發式方法。這種啟發式方法通常運行良好,但根據應用程序的特性,可能需要進行調整。此選項基本上決定了應該給出多少CPU時間。給它太多,GC將從應用程序中竊取過多的CPU時間。給它太少,應用程序可能比GC可以更快地分配垃圾。
注意!通常,如果低延遲(即低應用程序響應時間)對您的應用程序很重要,那么永遠不要過度配置您的系統。理想情況下,您的系統的CPU利用率絕不應超過70%。
啟用大頁面
配置ZGC以使用大頁面通常會產生更好的性能(在吞吐量,延遲和啟動時間方面)并且沒有真正的缺點,除了設置稍微復雜一點。設置過程通常需要root權限,這就是默認情況下未啟用的原因。
大頁面在Linux / x86上也稱為“大頁面”,大小為2MB。
假設你想要一個16G的Java堆。這意味著您需要16G / 2M = 8192個大頁面。
首先將至少16G(8192頁)的內存分配給大頁面池。“至少”部分很重要,因為在JVM中啟用大頁面意味著不僅GC會嘗試將這些用于Java堆,而且JVM的其他部分也會嘗試將它們用于各種內部數據結構(代碼堆,標記位圖等)。在此示例中,我們將保留9216頁(18G)以允許2G的非Java堆分配使用大頁面。
?
啟用透明大頁面
使用顯式大頁面(如上所述)的替代方法是使用透明的大頁面。對于延遲敏感的應用程序,通常不建議使用透明的大頁面,因為它往往會導致不必要的延遲峰值。但是,可能值得嘗試查看您的工作負載是否/如何受其影響。但請注意,您的里程可能會有所不同。
請注意,使用啟用了透明大頁面的ZGC需要Linux內核> = 4.7。
?
啟用NUMA支持
ZGC具有基本的NUMA支持,這意味著它將盡力將Java堆分配引導到NUMA本地內存。默認情況下啟用此功能。但是,如果JVM檢測到它綁定到系統中CPU的子集,它將自動禁用。通常,您不必擔心此設置,但如果要顯式覆蓋JVM的決策,則可以使用-XX:+UseNUMA或-XX:-UseNUMA選項來執行此操作。
在NUMA計算機(例如多插槽x86計算機)上運行時,啟用NUMA支持通常會顯著提升性能。
https://www.boost.org/doc/libs/1_69_0/libs/fiber/doc/html/fiber/numa.html
NUMA
現代微處理器包含通過通道連接到存儲器的集成存儲器控制器。訪問存儲器可以分為兩種:
統一存儲器訪問(UMA)和非統一存儲器訪問(NUMA)。
與UMA相比,UMA提供了一個集中的內存池(因此在一定數量的處理器之后無法擴展),NUMA架構將內存劃分為相對于微處理器的本地和遠程內存。
本地內存直接連接到處理器的集成內存控制器。連接到另一個微處理器(多插槽系統)的內存控制器的內存被視為遠程內存。如果內存控制器訪問遠程內存,則必須遍歷互連[8]并連接到遠程內存控制器。
因此,訪問遠程內存會增加本地內存訪問的額外延遲開銷。由于存儲位置不同,NUMA系統經驗豐富非統一?內存訪問時間。
因此,通過保持內存訪問本地來實現最佳性能。
ZGC:低延遲的垃圾回收器?
并行化處理階段
- 標記(
Marking); - 重定位(
Relocation)/壓縮(Compaction); - 重新分配集的選擇(
Relocation set selection); - 引用處理(
Reference processing); - 弱引用的清理(
WeakRefs Cleaning); - 字符串常量池(
String Table)和符號表(Symbol Table)的清理; - 類卸載(
Class unloading)。
ZGC 垃圾回收過程
ZGC 的垃圾回收算法和傳統的?Stop-The-World?式的垃圾回收算法不太一樣,后者的標記階段和內存壓縮階段會使得應用線程掛起。ZGC 和?C4(Continuously Concurrent Compacting Collector))算法比較類似。
一次完整的 ZGC 回收周期分為以下幾個階段(Phase):
Pause Mark Start:標記根對象;Concurrent Mark:并發標記階段;-
Concurrent Relocate:并發重定位;- 活動對象被移動到了一個新的?
Heap Region?B-region 中,之前舊對象所在的?Heap Region?A-region 即可復用;如果 B-region 中對象之間的引用關系將會在這一階段被更新; - 在重定位過程中,新舊對象的映射關系(同一對象在不同?
Region?中的映射關系)被記錄在了?Forwarding Tables?中。
- 活動對象被移動到了一個新的?
-
Pause Mark Start:這個階段實際上已經進入了新的?ZGC Cycle,同樣也是標記根對象; Concurrent Remap:并發重映射。 這個階段除了標記根對象直接引用的對象外,還會根據上個?ZGC Cycle?中生成的?Forwarding Tables?更新跨?Heap Region?的引用;Concurrent Relocate……
從上面的垃圾回收過程可以看到,正是因為 ZGC 回收過程中各個 Phase 的并發性,才使得?GC Pause?不受垃圾回收周期內堆上活動數據數量和需要跟蹤與更新的引用數量的影響,將暫停時間保持在較低的水平。
ZGC 的垃圾回收各階段也不都是并發執行的,在?Pause Mark Start?階段進行根對象掃描(Root Scanning)時會出現短暫的暫停。
ZGC 在內存整理和引用更新上采取了不同的策略,給垃圾回收過程帶來了巨大的性能提升。內存整理和引用更新都是并發的,也是交替進行的(其他的垃圾回收算法在更新引用時需要所有的線程到達?safe-point?)。但與此同時,我們也應該看到,并發帶來的 GC 吞吐率的下降也是不可忽視的。
當響應時間比吞吐量占有更高的優先級時,ZGC 是個不錯的選擇。而對那些不能接受長時間暫停的應用程序來說,ZGC 是個理想的選擇。而對于那些只是在后臺進行密集計算的應用程序,G1 或者 Parallel 垃圾回收器可能具有更好的垃圾回收性能。
?
ZGC 的介紹 PPT:
The Z Garbage Collector: Low Latency GC for OpenJDK。
總結
以上是生活随笔為你收集整理的Jdk11,Jdk12的低延迟垃圾收集器ZGC的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 求一个两个字的qq网名女!
- 下一篇: 协程和Java实现