java GC Collector

临渊不羡渔發表於2024-03-19

java 垃圾收集器

# 最小堆值,不設定預設為作業系統 1/64
-Xms4G
# 最大堆值,不設定預設為作業系統 1/4
-Xmx4G

G1

jdk9開始預設啟用,顯示啟用 -XX:+UseG1GC

介紹

  1. 伺服器級計算機上的垃圾優先 (G1) 收集器,否則為序列收集器。
  2. GC 執行緒的最大數量受堆大小和可用 CPU 資源的限制
  3. 初始堆大小為實體記憶體的 1/64
  4. 最大堆大小為實體記憶體的 1/4
  5. 分層編譯器,同時使用 C1 和 C2

常用配置方式(單選)

最大暫停時間期望

-XX:MaxGCPauseMillis=<nnn>

-XX:MaxGCPauseMillis=12 表示期望垃圾收集器的STW時間小於等於 12 毫秒。垃圾收集器動態調整 Java 堆大小和與垃圾收集相關的其他引數,以嘗試使垃圾收集暫停時間短於 12 毫秒。最大暫停時間目標的預設值因收集器而異。這些調整可能會導致垃圾收集更頻繁地發生,從而降低應用程式的整體吞吐量。但在某些情況下,無法達到所需的暫停時間目標。

吞吐量期望

# 垃圾收集時間與應用程式時間的比率為 1/(1+nnn)
-XX:MaxGCPauseMillis=<nnn>

-XX:GCTimeRatio=19 表示期望垃圾收集總時間為應用程式執行時間的 1/20 。
垃圾收集所花費的時間是所有垃圾收集引起的暫停的總時間。如果未達到吞吐量目標,則垃圾收集器可能採取的操作之一是增加堆的大小,以便在收集暫停之間應用程式所花費的時間可以更長。

ZGC

介紹

高資源佔用,低延時。支援範圍為幾百兆到16T的記憶體。是一種可擴充套件的低延遲垃圾收集器。ZGC 同時執行所有昂貴的工作,而不會停止應用程式執行緒的執行超過一毫秒。適合需要低延遲的應用。暫停時間與正在使用的堆大小無關。ZGC 可以很好地處理從幾百兆位元組到 16TB 的堆大小。

ZGC 被設計為自適應且需要最少的手動配置。在 Java 程式執行期間,ZGC 透過調整代大小、擴充套件 GC 執行緒數量以及調整保有閾值來動態適應工作負載。主要的調整旋鈕是增加最大堆大小。

使用命令

# 使用非分代ZGC(最早版本不支援分代)
-XX:+UseZGC
# 使用分代ZGC(官方推薦)
-XX:+UseZGC -XX:+ZGenerational

常用基礎配置

設值最大堆(最重要)

# 指定最大堆為8g
-Xmx8g
# 指定最大堆為5g,通常4g就開始GC,實在不行才會跑的5g,再不行就OOM
-Xmx5g -XX:SoftMaxHeapSize=4gZGC

禁用未用記憶體釋放

預設情況下,ZGC會將不需要用的記憶體釋放給作業系統。該功能對於外部程式都有意義,但是會對內部執行緒延長產生負面影響。

# 禁用未用記憶體釋放
-XX:-ZUncommit
# 由於最大堆和最小堆大小一致,也不會釋放未用記憶體給作業系統
-Xmx8g -Xms8g
# 未用記憶體返給作業系統延遲。預設 300 秒
-XX:ZUncommitDelay=<seconds>
# 極低延遲系統建議配置最大堆等於最小堆值,並啟動在應用程式之前記憶體分頁
-Xmx32g -Xms32g -XX:+AlwaysPreTouch

Using Large Pages(使用大頁面)

在 Linux x86 上,大頁面(huge page)的大小為 2MB
假設堆大小為16G。則表示需要16GB / 2MB = 8192 個大頁面。

# 需要root許可權,這個也是GC預設不採用ZGC的原因。
echo 9216 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
# 如果核心無法找到足夠的空閒大頁面來滿足請求,則上述命令可能失敗。而且核心可能需要一些時間來處理請求。在繼續後續操作之前,請確認配置已經生效
cat /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages

透明大頁面(在 Linux 上,核心 >= 4.7)

使用顯式大頁面(如前所述)的替代方法是使用透明大頁面。對於延遲敏感的應用程式,通常不建議使用透明大頁面,因為它往往會導致不必要的延遲峰值。但是,可能值得嘗試一下,看看您的工作負載是否或如何受到影響。

相關文章