1、概述:
對於JVM的垃圾回收器影響因素較多,例如:IO、臨時變量、常駐對象、對象大小、CPU等各種軟硬件配置,需要滿足的場景也存在差異,例如:吞吐量量優先、響應耗時優先,以及2者的平衡;所以以下是從本人負責的營銷業務各個系統之前調優歷程的一些總結,作為后續的參考方向。由於虛擬機比較多,以下描述主要是基於Hotspot。(以下簡稱營銷系統)
2、背景描述:
營銷主要核心系統之前部分接口存在耗時較大,經常觸發到報警閾值,進行了一系列調參;主要參考指標:接口耗時、YGC耗時、YGC次數、FGC耗時、FGC頻繁程度(次數);營銷核心系統JVM垃圾回收器選擇經歷了這么幾個階段:
ParNew + CMS----->G1----->ParNew + CMS----->PS(當前線上)
3、對於ParNew + CMS:
ParNew :
1、是Serial收集器的多線程版本,也使用復制算法
2、垃圾收集過程中同樣也要暫停所有其他的工作線程(缺點)
3、默認開啟和CPU數目相同的線程數
4、在Server模式下新生代的默認垃圾收集器
CMS:
特點:
1、是一種年老代垃圾收集器
2、最主要目標是獲取最短垃圾回收停頓時間
3、是Sun HotSpot虛擬機中第一款真正意義上並發垃圾收集器,它第一次實現了讓垃圾收集線程和用戶線程同時工作
4、最短的垃圾收集停頓時間可以為交互比較高的程序提高用戶體驗,高速響應
5、使用多線程的標記-清除算法
缺點:
1、對CPU資源敏感,在多CPU下才能體現優勢;雖然不會導致用戶線程停頓,但是占用CPU導致應用程序變慢,引起吞吐量下降;
2、永久代空間(或JDK8的元空間)耗盡,默認情況下,CMS不會對永久代進行收集,一旦永久代空間耗盡,就回觸發Full GC;
3、無法處理浮動垃圾,CMS在並發清理階段用戶線程依然在運行,並產生新垃圾(浮動垃圾),本次無法清除,需待下次GC清除;CMS的預留空間(-XX:CMSInitiatingOccupancyFraction設置預留空間占比)不夠用戶線程使用,會出現“Concurrent Mode Failure”失敗,此時JVM會臨時啟用Serial Old收集器來重新進行老年代的垃圾收集,導致停頓時間變長,性能反而降低;
4、會產生大量內存空間碎片,大量內存碎片可能實際老年代空間很多,但不夠大塊對象使用,導致提前觸發FGC;雖然CMS提供了碎片空間整理壓縮機制,但是整理過程不是並發,導致停頓變長;
對於CMS:-XX:ParallelCMSThreads:設定CMS的線程數量
適用場景:重視服務器響應速度,要求系統停頓時間最短。
但是有個明顯的弊端,就是當堆空間持續增大時,垃圾回收的時間也將會相應的持續增大,對應應用暫停的時間也會相應的增大。一些對相應時間要求很高的應用,比如最大暫停時間要求是幾百毫秒,那么當堆空間大於幾個G時,就很有可能超過這個限制,在這種情況下,垃圾回收將會成為系統運行的一個瓶頸。為解決這種矛盾,有了並發垃圾回收算法,使用這種算法,垃圾回收線程與程序運行線程同時運行。在這種方式下,解決了暫停的問題,但是因為需要在新生成對象的同時又要回收對象,算法復雜性會大大增加,系統的處理能力也會相應降低,同時,“碎片”問題將會比較難解決。所以,對於高並發系統,CMS也並非最優。
此階段營銷系統是環境是:JDK7 + 2核4G
4、對於G1:
特點:
1、JDK7引入,JDK8及以上成熟,JDK9默認收集器;
2、基於標記-整理算法,不產生內存碎片;
3、可以非常精確控制停頓時間,在不犧牲吐量前提下,實現低停頓垃圾回收;
4、G1收集器避免全區域垃圾收集,它把堆內存划分為大小固定的幾個獨立區域,並且跟蹤這些區域的垃圾收集進度,同時在后台維護一個優先級列表,每次根據所允許的收集時間,優先回收垃圾最多的區域;
缺點:
1、G1內部有個region區域塊的概念, 它的大小和大對象很難保證一致,這會導致空間的浪費;特別大的對象是可能占用超過一個 region 的。如果設置region大小不合理,會導致大對象分配空間時內存空間地址不連續。
適用場景:要求盡可能可控 GC 停頓時間;內存占用較大的應用。
此階段營銷系統是環境是:JDK7 + 2核4G;G1需要在多CPU、多核的情況下才能體現出優勢,加之促銷當時是JDK7,所以效果並不明顯,還沒有ParNew + CMS效果好。總體來說G1是一款厲害的垃圾回收器,不過要搭配上對應的環境;G1在低停頓優勢很明顯,但是系統追求高吞吐量,G1效果並不一定明顯。
5、對於PS:
Parallel Scavenge:
1、是一個新生代垃圾收集器,同樣使用復制算法
2、是一個多線程的垃圾收集器
3、它重點關注的是程序達到一個可控制的吞吐量
4、主要適用於在后台運算而不需要太多交互的任務
5、自適應調節策略也是ParallelScavenge收集器與ParNew收集器的一個重要區別
缺點:
1、回收的時間變短了,但是回收的次數會增多,這一點在促銷系統實踐上非常明顯。
Parallel Old:
1、是Parallel Scavenge的年老代版本
2、使用多線程的標記-整理算法
3、JDK7、JDK8 默認使用該收集器作為老年代收集器
缺點:
1、停頓時間長
應用場景:在Server模式,多CPU的情況下,如果系統對吞吐量要求比較高,可以優先考慮新生代Parallel Scavenge和年老代Parallel Old收集器的搭配策略。
此階段營銷系統是環境是:(J-one下)JDK7 + 2核4G;(Jdos下)JDK8 + 2核4G。此階段一個比較明顯的效果是YGC的時間縮短了,FGC的頻繁程度降低了;對於此搭配一個心得是需要結合NewRatio與SurvivorRatio等參數來調試,包括合理的Eden、From、To空間的設置才會有較優的效果。
6、營銷系統效果:
YGC時間變短了,之前有出現過80ms的情況,現在基本是在8ms~50ms之間;FGC的頻率明顯降低,甚至基本不發生FGC。
7、總結:
雖然以上是針對垃圾回收器的特點介紹和選擇,但促銷實際過程中還結合了很多其他JVM參數配套調試,所以要達到一個比較良好的效果需要結合系統配置、環境、代碼等因素綜合考慮;建議在壓測時候進行參數調試。平衡取舍,如果系統不關心耗時,那么內存允許的條件下直接開大內存搞,如果系統對耗時極為苛刻,那么JVM調優也只是一方面,有條件擴容還需擴容,以及升級配置。(典型例子:國內某些大型電商核心系統主要使用堆起高配機子策略,類似JVM細節配置反而次之)。