【JVM原理詳解】26-Parallel-Scavenge與吞吐量優(yōu)先
26-Parallel Scavenge 與吞吐量優(yōu)先上一篇講了 Serial 和 ParNew它們關注的是縮短單次 GC 停頓。但有一類應用并不在意某次停頓長短而在意單位時間內(nèi)完成的業(yè)務量——例如離線數(shù)據(jù)分析、批處理任務、ETL 作業(yè)。為這類場景HotSpot 提供了Parallel Scavenge / Parallel Old收集器它的設計目標是吞吐量優(yōu)先。本篇將剖析它的原理、關鍵參數(shù)、自適應調(diào)節(jié)機制以及它與 ParNew 的本質(zhì)區(qū)別。吞吐量的定義GC 語境下的吞吐量Throughput有精確含義吞吐量 運行用戶代碼時間 / (運行用戶代碼時間 GC 時間)注意這不是每秒處理請求數(shù)而是用戶代碼運行時間占總時間的比例。一個 99% 吞吐量的系統(tǒng)意味著 100 秒里有 99 秒在跑業(yè)務1 秒在做 GC。舉個例子對比延遲優(yōu)先與吞吐量優(yōu)先方案A延遲優(yōu)先每 1 秒 GC 一次每次 10ms → 吞吐量 990/1000 99% 方案B吞吐優(yōu)先每 10 秒 GC 一次每次 50ms → 吞吐量 9950/10000 99.5%方案 B 單次停頓更長50ms vs 10ms但總 GC 時間更少吞吐量更高。對于不與用戶交互的后臺任務方案 B 更合適——這正是 Parallel Scavenge 的設計哲學。Parallel Scavenge 收集器Parallel Scavenge 是新生代收集器基于復制算法多線程并行回收回收時 STW。聽起來和 ParNew 很像但它有兩個關鍵差異目標不同ParNew 追求降低單次停頓Parallel Scavenge 追求達到可量化的吞吐量。自適應它能根據(jù)運行情況動態(tài)調(diào)整新生代大小、Eden/Survivor 比例、晉升老年代年齡等參數(shù)無需人工調(diào)參。新生代布局 ┌───────────────────────────────────┐ │ Eden │ S0 │ S1 │ │ (8/10) │(1/10)│(1/10)│ └───────────────────────────────────┘ ↑ 復制算法多線程并行與 ParNew 的本質(zhì)區(qū)別兩者表面都是多線程復制算法但底層實現(xiàn)完全不同維度ParNewParallel Scavenge設計目標降低停頓達到吞吐量目標可搭配老年代CMS / Serial OldParallel Old自適應調(diào)節(jié)無有UseAdaptiveSizePolicy代碼框架與 CMS 共享獨立實現(xiàn)參數(shù)控制停頓為主吞吐量為主最關鍵的差異是Parallel Scavenge 關注的是吞吐量這個全局指標而不是單次停頓。它允許偶爾一次較長的 GC只要總體 GC 時間占比足夠低即可。Parallel Old 收集器Parallel Old 是 Parallel Scavenge 的老年代搭檔多線程、Mark-Compact 算法、STW。在 JDK 6 之前Parallel Scavenge 只能搭配 Serial Old單線程老年代導致老年代 GC 成為瓶頸。Parallel Old 的出現(xiàn)讓全堆并行吞吐量優(yōu)先成為可能。# JDK 8 默認收集器組合Server 模式java-XX:UseParallelGC-XX:UseParallelOldGC-cpMyApp com.example.Main實際上 JDK 8 Server 模式下這就是默認組合無需顯式指定。JDK 9 起-XX:UseParallelOldGC和-XX:UseParallelGC合并開啟一個即同時啟用兩者。三大核心參數(shù)Parallel Scavenge 之所以叫吞吐量優(yōu)先靠的是下面三個參數(shù)的協(xié)同。-XX:MaxGCPauseMillis設置最大 GC 停頓時間目標毫秒。JVM 會盡量讓單次 GC 停頓不超過這個值方法是縮小新生代——新生代越小回收越快。java-XX:MaxGCPauseMillis50-cpMyApp com.example.Main但這里有個陷阱停頓目標是軟約束不是硬保證。JVM 會努力逼近但不保證每次都達標。更危險的是盲目調(diào)小這個值會導致新生代被壓縮GC 頻率上升反而降低吞吐量。MaxGCPauseMillis50 → 新生代縮小 → 單次快但頻繁 → 吞吐量下降 MaxGCPauseMillis200 → 新生代擴大 → 單次慢但稀少 → 吞吐量上升這是一個需要根據(jù)實際負載權衡的參數(shù)。對吞吐量優(yōu)先的后臺任務適當放大停頓目標反而更優(yōu)。-XX:GCTimeRatio直接以比例方式設定吞吐量目標。GCTimeRatioN表示 GC 時間占總時間的1/(N1)GCTimeRatio99 → 吞吐量目標 99/(991) 99% GCTimeRatio19 → 吞吐量目標 19/(191) 95% GCTimeRatio9 → 吞吐量目標 9/(91) 90%默認值默認值 9 意味著 JVM 默認目標是 90% 吞吐量。對于生產(chǎn)服務偏低通常調(diào)到 19 或 99。GCTimeRatio和MaxGCPauseMillis可能沖突——一個要低停頓小新生代一個要高吞吐大新生代。沖突時 JVM 以MaxGCPauseMillis優(yōu)先這可能導致吞吐量目標無法達成。-XX:UseAdaptiveSizePolicy這是 Parallel Scavenge 最具特色的參數(shù)自適應調(diào)節(jié)。開啟后JVM 根據(jù)運行歷史動態(tài)調(diào)整新生代 / 老年代大小比例Eden / Survivor 比例對象晉升老年代的年齡閾值java-XX:UseParallelGC-XX:UseAdaptiveSizePolicy\-XX:MaxGCPauseMillis100-XX:GCTimeRatio19\-cpMyApp com.example.Main開啟自適應后你只需給出目標停頓或吞吐量JVM 自己找參數(shù)。這是聲明式調(diào)優(yōu)的早期實踐與 G1、ZGC 的設計思路一脈相承。自適應的工作機制JVM 內(nèi)部維護一組運行統(tǒng)計最近 N 次 GC 的停頓時長、吞吐量、各區(qū)域占用。每次 GC 后根據(jù)這些統(tǒng)計決定是否調(diào)整區(qū)域大小if (實測停頓 MaxGCPauseMillis) { 縮小新生代 → 下次 GC 更快 } else if (實測吞吐量 目標吞吐量) { 擴大新生代 → 減少 GC 頻率 } // 同時調(diào)整 Eden/Survivor 比例、晉升年齡這種反饋機制讓 Parallel Scavenge 在負載波動的場景下表現(xiàn)穩(wěn)健——不需要人工介入JVM 自己會找到平衡點。代碼示例觀察自適應調(diào)節(jié)/** * 演示 Parallel Scavenge 自適應調(diào)節(jié) * 適用 JDK 8/11/17 * * 運行 * java -Xms256m -Xmx256m -XX:UseParallelGC * -XX:UseAdaptiveSizePolicy * -XX:MaxGCPauseMillis50 -XX:GCTimeRatio19 * -Xlog:gc*info,gcheapdebug -cp MyApp AdaptiveGcDemo */publicclassAdaptiveGcDemo{privatestaticfinalint_1MB1024*1024;publicstaticvoidmain(String[]args)throwsException{// 模擬波動的分配速率for(inti0;i100;i){byte[]blocknewbyte[_1MB];// 偶爾保留引用制造長期存活對象if(i%100){cache(block);}Thread.sleep(20);}}staticfinaljava.util.Listbyte[]CACHEnewjava.util.ArrayList();staticvoidcache(byte[]block){CACHE.add(block);}}觀察日志中新生代大小的變化[0.234s][info][gc,heap] GC(0) PSYoungGen total 76288K, used 65536K ... [1.567s][info][gc,heap] GC(5) PSYoungGen total 152576K, used 131072K ... [3.891s][info][gc,heap] GC(12) PSYoungGen total 101376K, used 81920K ...PSYoungGen是 Parallel Scavenge 新生代的內(nèi)部名PS Parallel Scavenge??梢钥吹絫otal大小在多次 GC 后發(fā)生了變化——這正是自適應調(diào)節(jié)在起作用。與 ParNew 的選擇實際項目中如何在兩者間選擇決策核心是對停頓還是吞吐更敏感對用戶交互的 Web 服務 → 停頓敏感 → ParNew CMSJDK 8或 G1JDK 9 對后臺批處理 / ETL → 吞吐敏感 → Parallel Scavenge Parallel Old 對延遲敏感且堆大 → G1 / ZGC一個實際案例某公司夜間跑離線報表每天凌晨 2 點啟動一個 Java 進程處理 50GB 數(shù)據(jù)跑 2 小時。這種場景不與用戶交互停頓 200ms 也無所謂。但 2 小時內(nèi) GC 總時間越少越好。→Parallel Scavenge Parallel Old是最優(yōu)解。反過來一個在線 API 服務P99 延遲要求 50ms此時即使吞吐量 99%一次 200ms 的停頓也會打爆 SLA——應選 G1 或 ZGC。適用場景后臺計算與批處理Hadoop/Spark 的 JVM 進程MapReduce 任務不與用戶交互吞吐量第一。ETL 數(shù)據(jù)管道定時跑數(shù)據(jù)清洗只看總耗時。離線訓練 / 模型推理批處理對單次延遲不敏感。歷史服務JDK 8 默認JDK 8 Server 模式默認就是 Parallel Scavenge Parallel Old。很多遺留系統(tǒng)跑在這套組合上運行多年沒出大問題——說明對吞吐不敏感到吞吐重要的中間地帶它是可靠的選擇。不適用場景交互式 Web 服務停頓不可控可能突然出現(xiàn) 200ms 的長尾。低延遲交易系統(tǒng)單次停頓超 10ms 就會影響交易。大堆 8GBParallel Old 整理老年代時全堆 STW堆越大停頓越長。實踐要點1. 不要同時設 MaxGCPauseMillis 和 GCTimeRatio 且相互矛盾# 矛盾配置要 50ms 停頓又要 99% 吞吐-XX:MaxGCPauseMillis50-XX:GCTimeRatio99JVM 會以MaxGCPauseMillis優(yōu)先GCTimeRatio形同虛設。選一個作為主目標即可。2. 自適應開啟后不要手動固定新生代# 錯誤開了自適應又固定新生代-XX:UseAdaptiveSizePolicy-Xmn100m-Xmn或-XX:NewRatio會和自適應沖突。開啟自適應后讓 JVM 自己管區(qū)域大小。3. 監(jiān)控 GC 頻率而非單次停頓吞吐量優(yōu)先場景下單次停頓波動正常。關注單位時間內(nèi) GC 總時間和吞吐量百分比這兩個指標更能反映健康度。JDK 11 日志會在每次 GC 后輸出User/Sys/Real時間可據(jù)此計算。4. Parallel Old 的 Full GC 是 STW 的[12.345s][info][gc]GC(20)Pause Full(Ergonomics)800M-600M(1G)234.567ms(Ergonomics)表示觸發(fā)原因是自適應策略決定該做 Full GC 了。注意 Full GC 停頓隨堆線性增長4GB 堆可能輕松到秒級。大堆場景應遷移到 G1。5. JDK 8 升級到 JDK 11 時的遷移JDK 11 默認 G1若你的批處理任務在 JDK 8 用 Parallel Scavenge 表現(xiàn)良好可以顯式保留java-XX:UseParallelGC-cpMyApp com.example.BatchJob對于批處理任務不必盲目切 G1——Parallel Scavenge 的吞吐量優(yōu)勢在純計算場景下依然存在。小結Parallel Scavenge / Parallel Old是吞吐量優(yōu)先的收集器組合新生代復制算法、老年代 Mark-Compact全多線程并行。吞吐量 用戶代碼時間 / (用戶代碼時間 GC 時間)與低停頓是不同的優(yōu)化目標后者允許總 GC 時間更多。三大核心參數(shù)MaxGCPauseMillis停頓目標、GCTimeRatio吞吐量目標、UseAdaptiveSizePolicy自適應開關三者協(xié)同讓 JVM 自行尋優(yōu)。與 ParNew 的本質(zhì)區(qū)別在于設計目標和自適應能力代碼實現(xiàn)也相互獨立二者不可混搭。適用場景后臺批處理、離線數(shù)據(jù)分析、ETL 作業(yè)等不與用戶交互的吞吐量敏感型任務交互式 Web 服務應選 G1 或 ZGC。下一篇我們將進入垃圾收集器的并發(fā)時代——CMS 收集器它是第一款真正讓老年代回收與應用線程并發(fā)的收集器也是理解 G1、ZGC 并發(fā)回收思路的關鍵階梯。更多內(nèi)容JVM調(diào)優(yōu)實戰(zhàn)

相關新聞

H1 H6 標題 層級 內(nèi)容 結構 SEO: 降低跳出率的秘訣:優(yōu)化層次的4個實用技巧

H1 H6 標題 層級 內(nèi)容 結構 SEO: 降低跳出率的秘訣:優(yōu)化層次的4個實用技巧

某款月訪問量四萬的獨立博客在過去半年里,訪客平均單頁停留時長跌至三十四秒,跳出率常年維持在百分之七十八。運營團隊調(diào)取日志發(fā)現(xiàn),百分之六十五的訪客在點開文章后五秒內(nèi)關閉頁面。排查發(fā)現(xiàn),問題出在文章排版:主標題…

2026/8/1 0:29:33 閱讀更多
《javaweb的基礎》0基礎學習前端內(nèi)容--vue框架

《javaweb的基礎》0基礎學習前端內(nèi)容--vue框架

首先申明,這是基礎內(nèi)容,為的是帶大家了解vue這個內(nèi)容,嘗試學習vue基礎知識,其實vue是一個很大的知識體系,這里我簡單的講述了一下對于前后端數(shù)據(jù)傳輸后的數(shù)據(jù)最基本的處理,不涉及生態(tài),只是對交互…

2026/8/2 5:04:57 閱讀更多
從Google Earth提取實景三維模型:SfM重建實戰(zhàn)指南

從Google Earth提取實景三維模型:SfM重建實戰(zhàn)指南

1. 項目概述:從數(shù)字地球到三維資產(chǎn) 幾年前,我接手一個城市微更新項目,需要快速獲取項目地塊及周邊環(huán)境的精確三維模型作為設計基底。當時第一反應就是打開Google Earth——這個幾乎人人都用過的“數(shù)字地球儀”。它的三維視圖如此逼真&#xf…

2026/8/2 5:04:57 閱讀更多
Power BI數(shù)據(jù)建模核心:表間關系創(chuàng)建、管理與性能優(yōu)化實戰(zhàn)指南

Power BI數(shù)據(jù)建模核心:表間關系創(chuàng)建、管理與性能優(yōu)化實戰(zhàn)指南

1. 項目概述:為什么表間關系是數(shù)據(jù)模型的靈魂如果你用過Power BI,肯定知道拖拽字段就能出圖表的爽快感。但很多朋友做到后面就卡住了,報表越做越慢,數(shù)據(jù)算出來總是不對,或者想做個稍微復雜點的分析就無從下手。這些問題…

2026/8/2 5:04:57 閱讀更多
3分鐘搞定!QQ空間歷史說說完整備份終極指南

3分鐘搞定!QQ空間歷史說說完整備份終極指南

3分鐘搞定!QQ空間歷史說說完整備份終極指南 【免費下載鏈接】GetQzonehistory 獲取QQ空間發(fā)布的歷史說說 項目地址: https://gitcode.com/GitHub_Trending/ge/GetQzonehistory 你是否曾想過,那些年發(fā)過的QQ空間說說,那些記錄青春的文字…

2026/8/2 0:04:01 閱讀更多
3分鐘搞定!QQ空間歷史說說完整備份終極指南

3分鐘搞定!QQ空間歷史說說完整備份終極指南

3分鐘搞定!QQ空間歷史說說完整備份終極指南 【免費下載鏈接】GetQzonehistory 獲取QQ空間發(fā)布的歷史說說 項目地址: https://gitcode.com/GitHub_Trending/ge/GetQzonehistory 你是否曾想過,那些年發(fā)過的QQ空間說說,那些記錄青春的文字…

2026/8/2 0:04:01 閱讀更多
AMAT 0100-02186 I/O 分配 PCB

AMAT 0100-02186 I/O 分配 PCB

AMAT 0100-02186 I/O分配PCB板是應用材料(Applied Materials)公司生產(chǎn)的一款用于半導體設備的I/O信號分配電路板。該型號(0100-02186)的核心特點如下:專用于Endura等半導體工藝腔室。集成信號路由與分配功能。連接控制…

2026/8/2 2:51:21 閱讀更多
Nissei Corp FFMN-32L-10-T0 40AX 三相異步電動機

Nissei Corp FFMN-32L-10-T0 40AX 三相異步電動機

Nissei Corp FFMN-32L-10-T0 40AX 三相異步電動機是日本日清(Nissei)品牌的一款工業(yè)用三相異步電機,適用于自動化設備及通用機械驅(qū)動。該型號(FFMN-32L-10-T0 40AX)的核心特點如下:三相交流異步電動機。額定…

2026/8/2 2:52:49 閱讀更多