G1 GC 調優學習 瞭解有關如何調整和調整G1 GC以進行評估,分析和性能的信息。

 G1 GC是Java HotSpot虛擬機的低暫停服務器風格分代垃圾收集器。G1 GC使用併發(concurrent)和並行(parallel)階段來實現其目標暫停時間並保持良好的吞吐量。當G1 GC確定需要進行垃圾收集時,它將首先收集存活數據最少的區域(垃圾優先處理)。

垃圾收集器(GC)是一種內存管理工具。G1 GC通過以下操作實現自動內存管理:

  • 在年輕一代分配對象,並將老化的對象提升爲老一代。
  • 在併發(並行)標記階段,在老一代中查找存活對象。當Java堆總佔用量超過默認閾值時,Java HotSpot VM會觸發標記階段。
  • 通過並行複製,壓縮存活對象來恢復可用內存。

在這裏,我們研究如何適應和調整G1 GC以進行評估,分析和性能-我們假設對Java垃圾收集有基本的瞭解。

G1 GC是一個區域化的代垃圾收集器,這意味着Java對象堆(堆)被劃分爲多個大小相等的區域。啓動時,Java虛擬機(JVM)設置區域大小。區域大小可以從1 MB到32 MB不等,具體取決於堆大小。目標是不超過2048個區域。Eden,survivor和老年代是這些地區的邏輯集合,並不相鄰。

G1 GC 有一個力求達到的暫停時間目標(軟實時)。在年輕代回收期間,G1 GC 會調整年輕代空間(eden 和survivors大小)以滿足軟實時目標。在混合回收期間,G1 GC 會根據混合垃圾回收的目標次數調整所回收的old區域數量,並調整堆的每個區域中存活對象的百分比,以及總體可接受的堆廢物百分比。

G1 GC 將一組或多組區域(稱爲Collection Set (CSet))中的存活對象以增量、並行的方式複製到不同的一個或者n個新區域來實現壓縮,從而減少堆碎片(類似young區的複製算法)。目標是從可回收空間最多的區域開始,儘可能回收更多的堆空間,同時儘可能不超出暫停時間目標(垃圾優先)。

G1 GC 使用獨立的記憶集 (Remembered Sets RSet) 跟蹤對區域的引用。獨立的 RSet 可以並行、獨立地回收區域,因爲只需要對區域(而不是整個堆)的 RSet 進行區域引用掃描。G1 GC 使用後寫屏障記錄堆的更改和更新 RSet。

垃圾回收階段(翻譯成 gc準備階段 比較好吧)

除了構成停頓 (STW) 年輕代和混合垃圾回收的排空操作(evacuation)暫停(如下所述),G1 GC 還具有並行、併發和多階段標記週期。G1 GC 使用初始快照 (SATB----Snapshot-At-The-Beginning) 算法,在標記週期之初爲堆中的存活對象集創建快照。存活對象集包括快照中的存活對象,以及標記週期開始以來所分配的對象。G1 GC 標記算法使用預寫屏障記錄和標記作爲邏輯快照一部分的對象。

young gc(young gc)

G1 GC 可滿足來自被添加到 eden 區域集的區域的大多數分配請求。在年輕代垃圾回收期間,G1 GC 會同時回收 eden 區域和上次垃圾回收的survivor區域。Eden 和survivor區的存活對象將被複制或疏散到新的區域集。特定對象的目標區域取決於對象的年齡;足夠老的對象疏散到老年代區域(也就晉級);否則疏散到survivor區,並將包含在下一次年輕代或混合垃圾回收的 CSet 中。

mixed gc(full gc,全局gc  mixed gc 新概念,不同於full gc)

成功完成併發標記週期後,G1 GC 從執行young gc切換爲執行mixed gc。在mixed gc期間,G1 GC 可以將一些old區域添加到將要被垃圾回收的 eden 和survivor區(翻譯一下就是mixed gc會回收一些old區和 young區)。所添加old區域的確切數量由一系列標誌控制。關於標誌的信息,將在後面討論(請參見“掌握混合垃圾回收”)。G1 GC 回收了足夠的old區域後(經過多次混合垃圾回收),G1 將恢復執行年輕代垃圾回收,直到下一個標記週期完成。

標記週期的各個階段

標記週期包括以下幾個階段:

  • 初始標記階段:在此階段,G1 GC 對根進行標記。該階段與常規的 (STW) 年輕代垃圾回收密切相關。
  • 根區域掃描階段:G1 GC 在初始標記的存活區掃描對老年代的引用,並標記被引用的對象。該階段與應用程序(非 STW)同時運行,並且只有完成該階段後,才能開始下一次 STW 年輕代垃圾回收。
  • 併發標記階段:G1 GC 在整個堆中查找可訪問的(存活的)對象。該階段與應用程序同時運行,可以被 STW 年輕代垃圾回收中斷。
  • 重新標記階段:該階段是 STW 回收,幫助完成標記週期。G1 GC 清空 SATB 緩衝區,跟蹤未被訪問的存活對象,並執行引用處理。
  • 清理階段:在這個最後階段,G1 GC 執行統計和 RSet 淨化的 STW 操作。在統計期間,G1 GC 會識別完全空閒的區域和可供進行混合垃圾回收的區域。清理階段在將空白區域重置並返回到空閒列表時爲部分併發。

重要的默認值

G1 GC 是自適應的垃圾回收器,提供了若干默認設置,使其無需修改即可高效地工作。以下是重要選項及其默認值的列表。此列表適用於最新的 Java HotSpot VM build 24。您可以通過在 JVM 命令行輸入下列選項和已更改的設置,根據您的應用程序性能需求調整和調優 G1 GC。

  • -XX:G1HeapRegionSize=n

    設置the size of a G1 region的大小。值是 2 的冪,範圍是 1 MB 到 32 MB 之間。目標是根據最小的 Java 堆大小劃分出約 2048 個區域。

  • -XX:MaxGCPauseMillis=200

    設置最長暫停時間目標值。默認值是 200 毫秒。

  • -XX:G1NewSizePercent=5

    設置年輕代最小值所佔總堆的百分比。默認值是堆的 5%。這是一個實驗性的標誌。有關示例,請參見“如何解鎖實驗性虛擬機標誌”。此設置取代了 -XX:DefaultMinNewGenPercent 設置。Java HotSpot VM build 23 中沒有此設置。

  • -XX:G1MaxNewSizePercent=60

    設置年輕代最大值所佔總堆的百分比。默認值是 Java 堆的 60%。這是一個實驗性的標誌。有關示例,請參見“如何解鎖實驗性虛擬機標誌”。此設置取代了 -XX:DefaultMaxNewGenPercent 設置。Java HotSpot VM build 23 中沒有此設置。

  • -XX:ParallelGCThreads=n

    設置 STW 工作線程數的值。將 n 的值設置爲邏輯處理器的數量。n 的值與邏輯處理器的數量相同,最多爲 8。

    如果邏輯處理器不止八個,則將 n 的值設置爲邏輯處理器數的 5/8 左右。這適用於大多數情況,除非是較大的 SPARC 系統,其中 n 的值可以是邏輯處理器數的 5/16 左右。

  • -XX:ConcGCThreads=n

    設置並行標記的線程數。將 n 設置爲並行垃圾回收線程數 (ParallelGCThreads) 的 1/4 左右。

  • -XX:InitiatingHeapOccupancyPercent=45

    設置觸發標記週期的 Java 堆佔用率閾值。默認佔用率是整個 Java 堆的 45%。

  • -XX:G1MixedGCLiveThresholdPercent=65

    爲混合垃圾回收週期中要包括的old區域設置佔用率閾值。默認佔用率爲 65%。這是一個實驗性的標誌。有關示例,請參見“如何解鎖實驗性虛擬機標誌”。此設置取代了 -XX:G1OldCSetRegionLiveThresholdPercent 設置。Java HotSpot VM build 23 中沒有此設置。

  • -XX:G1HeapWastePercent=10

    設置您願意浪費的堆百分比。如果可回收百分比小於堆廢物百分比,Java HotSpot VM 不會啓動混合垃圾回收週期。默認值是 10%。Java HotSpot VM build 23 中沒有此設置。

  • -XX:G1MixedGCCountTarget=8

    設置標記週期完成後,對存活數據上限爲 G1MixedGCLIveThresholdPercent 的old區域執行混合垃圾回收的目標次數。默認值是 8 次混合垃圾回收。混合回收的目標是要控制在此目標次數以內。Java HotSpot VM build 23 中沒有此設置。

  • -XX:G1OldCSetRegionThresholdPercent=10

    設置混合垃圾回收期間要回收的最大old區域數。默認值是 Java 堆的 10%。Java HotSpot VM build 23 中沒有此設置。

  • -XX:G1ReservePercent=10

    設置作爲空閒空間的預留內存百分比,以降低目標空間溢出的風險。默認值是 10%。增加或減少百分比時,請確保對總的 Java 堆調整相同的量。Java HotSpot VM build 23 中沒有此設置。

如何解鎖實驗性虛擬機標誌

要更改實驗性標誌的值,必須先對其解鎖。解鎖方法是:在命令行中的實驗性標誌前,顯式地設置 -XX:+UnlockExperimentalVMOptions。例如:

> java -XX:+UnlockExperimentalVMOptions -XX:G1NewSizePercent=10 -XX:G1MaxNewSizePercent=75 G1test.jar

建議

評估和微調 G1 GC 時,請記住以下建議:

  • 年輕代大小:避免使用 -Xmn 選項或 -XX:NewRatio 等其他相關選項顯式設置年輕代大小。固定年輕代的大小會覆蓋暫停時間目標。
  • 暫停時間目標:每當對垃圾回收進行評估或調優時,都會涉及到延遲與吞吐量的權衡。G1 GC 是增量垃圾回收器,暫停統一,同時應用程序線程的開銷也更多。G1 GC 的吞吐量目標是 90% 的應用程序時間和 10%的垃圾回收時間。如果將其與 Java HotSpot VM 的吞吐量回收器相比較,目標則是 99% 的應用程序時間和 1% 的垃圾回收時間。因此,當您評估 G1 GC 的吞吐量時,暫停時間目標不要太嚴苛。目標太過嚴苛表示您願意承受更多的垃圾回收開銷,而這會直接影響到吞吐量。當您評估 G1 GC 的延遲時,請設置所需的(軟)實時目標,G1 GC 會盡量滿足。副作用是,吞吐量可能會受到影響。
  • 掌握混合垃圾回收:當您調優混合垃圾回收時,請嘗試以下選項。有關這些選項的信息,請參見“重要的默認值”:
    • -XX:InitiatingHeapOccupancyPercent 用於更改標記閾值。
    • -XX:G1MixedGCLiveThresholdPercent 和 -XX:G1HeapWastePercent 當您想要更改混合垃圾回收決定時。
    • -XX:G1MixedGCCountTarget 和 -XX:G1OldCSetRegionThresholdPercent 當您想要調整舊區域的 CSet 時。

有關溢出和用盡的日誌消息

當您在日誌中看到目標空間溢出/用盡的消息時,意味着 G1 GC 沒有足夠的內存,供存活者和/或晉升對象使用。Java 堆不能擴展,因爲已達到最大值。示例消息:

924.897: [GC pause (G1 Evacuation Pause) (mixed) (to-space exhausted), 0.1957310 secs]

924.897:[GC pause (G1 Evacuation Pause) (mixed) (to-space overflow), 0.1957310 secs]

要緩解此問題,請嘗試以下調整:

增加 -XX:G1ReservePercent 選項的值(並相應增加總的堆大小),爲“目標空間”增加預留內存量。

通過減少 -XX:InitiatingHeapOccupancyPercent 提前啓動標記週期。

您也可以通過增加 -XX:ConcGCThreads 選項的值來增加並行標記線程的數目。

有關這些選項的描述,請參見“重要的默認值”。

巨型對象和巨型分配

對於 G1 GC,任何超過區域一半大小的對象都被視爲“巨型對象”。此類對象直接被分配到老年代中的“巨型區域”。這些巨型區域是一個連續的區域集(n個地址連續的region,爲的是可以拿出來連續的地址給大對象分配空間)。StartsHumongous 標記該連續集的開始,ContinuesHumongous 標記它的延續。

在分配任何巨型區域之前,會檢查標記閾值,如有必要,還會啓動一個併發週期。

在清理階段或完整的垃圾回收週期內,標記週期結束時會清理死亡的巨型對象。

爲了減少複製開銷,巨型對象未包括在疏散暫停中(young gc中爲了減少暫停,等mixed gc的時候再操作H區)。完整的垃圾回收週期會對巨型對象進行壓縮。

由於每個 StartsHumongous 和 ContinuesHumongous 區域集只包含一個巨型對象,所以沒有使用巨型對象的終點與上個區域的終點之間的空間(即巨型對象所跨的空間)。如果對象只是略大於堆區域大小的倍數,則此類未使用的空間可能會導致堆碎片化。

如果巨型分配導致連續的併發週期,並且此類分配導致老年代碎片化,請增加 -XX:G1HeapRegionSize,這樣一來,之前的巨型對象就不再是巨型對象了,而是採用常規的分配路徑。

總結

G1 GC 是區域化、並行-併發、增量式垃圾回收器,相比其他 HotSpot 垃圾回收器,可提供更多可預測的暫停。增量的特性使 G1 GC 適用於更大的堆,在最壞的情況下仍能提供不錯的響應。G1 GC 的自適應特性使 JVM 命令行只需要軟實時暫停時間目標的最大值以及 Java 堆大小的最大值和最小值,即可開始工作。

Garbage First Garbage Collector Tuning

弄個圖,可視化一下Java heap區究竟怎麼在那分配的

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章