談JVM參數GC線程數ParallelGCThreads合理性設置
作者:京東零售 劉樂
1. ParallelGCThreads參數含義
在講這個參數之前,先談談JVM垃圾回收(GC)算法的兩個優化標的:吞吐量和停頓時長。JVM會使用特定的GC收集線程,當GC開始的時候,GC線程會和業務線程搶佔CPU時間,吞吐量定義為CPU用於業務線程的時間與CPU總消耗時間的比值。為了承接更大的流量,吞吐量越大越好。
為了安全的垃圾回收,在GC或者GC某個階段,所有業務線程都會被暫停,也就是STW(Stop The World),STW持續時間就是停頓時長,停頓時長影響響應速度,因此越小越好。
這兩個優化目標是有衝突的,在一定範圍內,參與GC的線程數越多,停頓時長越小,但吞吐量也越小。生產實踐中,需要根據業務特點設置一個合理的GC線程數,取得吞吐量和停頓時長的平衡。
目前廣泛使用的GC算法,包括PS MarkSweep/PS Scavenge, ConcurrentMarkSweep/ParNew, G1等,都可以通過ParallelGCThreads參數來指定JVM在並行GC時參與垃圾收集的線程數。該值設置過小,GC暫停時間變長影響RT,設置過大則影響吞吐量,從而導致CPU過高。
2. ParallelGCThreads參數設置
GC併發線程數可以通過JVM啟動參數: -XX:ParallelGCThreads=<N>來指定。在未明確指定的情況下,JVM會根據邏輯核數ncpus,採用以下公式來計算默認值:
◦當ncpus小於8時,ParallelGCThreads = ncpus
◦否則 ParallelGCThreads = 8 + (ncpus - 8 ) ( 5/8 )
一般來説,在無特殊要求下,ParallelGCThreads參數使用默認值就可以了。但是在JRE版本1.8.0_131之前,JVM無法感知Docker的CPU限制,會使用宿主機的邏輯核數計算默認值。 比如部署在128核物理機上的容器,JVM中默認ParallelGCThreads為83,遠超過了容器的核數。過多的GC線程數搶佔了業務線程的CPU時間,加上線程切換的開銷,較大的降低了吞吐量。因此JRE 1.8.0_131之前的版本,未明確指定ParallelGCThreads會有較大的風險。
3. ParallelGCThreads參數實驗
創建 8C12G 容器,宿主機是128C。模擬線上真實流量,採用相同QPS,觀察及對比JVM YoungGC,JVM CPU,容器CPU等監控數據。場景如下:
◦場景1: JVM ParallelGCThreads 默認值,QPS = 420,持續5分鐘,CPU恆定在70%
◦場景2: JVM ParallelGCThreads=8,QPS = 420,持續5分鐘,CPU恆定在65%
◦場景3: JVM ParallelGCThreads 默認值,QPS瞬時發壓到420,前1min CPU持續100%
◦場景4: JVM ParallelGCThreads=8,QPS瞬時發壓到420,前2s CPU持續100%,後面回落
從監控數據來看,各場景下CPU差距較明顯,特別是場景3和場景4的對比。場景3由於GC線程過多,CPU持續100%時長達1分鐘。可以得出以下兩個結論:
1.修改 ParallelGCThreads = 8後,同等QPS情況下,CPU會降低5%左右
2.修改 ParallelGCThreads = 8後,瞬間發壓且CPU打滿情況下,CPU恢復較快
圖1: 容器CPU對比圖:場景3(上)和場景4(下)
圖2: JVM Young GC對比圖:場景3(上)和場景4(下)
4. ParallelGCThreads修改建議
ParallelGCThreads配置存在風險的應用,修改方式為以下兩種方案(任選一種):
◦升級JRE版本到1.8.0_131以上,推薦1.8.0_192
◦在JVM啟動參數明確指定 -XX:ParallelGCThreads=<N>,N為下表的推薦值:
容器核數 | 2 | 4 | 8 | 16 | 32 | 64 |
---|---|---|---|---|---|---|
推薦值 | 2 | 4 | 8 | 13 | 23 | 43 |
建議上下界 | 1~2 | 2~4 | 4~8 | 8~16 | 16~32 | 32~64 |
- 應用健康度隱患刨析解決系列之數據庫時區設置
- 對於Vue3和Ts的心得和思考
- 一文詳解擴散模型:DDPM
- zookeeper的Leader選舉源碼解析
- 一文帶你搞懂如何優化慢SQL
- 京東金融Android瘦身探索與實踐
- 微前端框架single-spa子應用加載解析
- cookie時效無限延長方案
- 聊聊前端性能指標那些事兒
- Spring竟然可以創建“重複”名稱的bean?—一次項目中存在多個bean名稱重複問題的排查
- 京東金融Android瘦身探索與實踐
- Spring源碼核心剖析
- 深入淺出RPC服務 | 不同層的網絡協議
- 安全測試之探索windows遊戲掃雷
- 關於數據庫分庫分表的一點想法
- 對於Vue3和Ts的心得和思考
- Bitmap、RoaringBitmap原理分析
- 京東小程序CI工具實踐
- 測試用例設計指南
- 當你對 redis 説你中意的女孩是 Mia