標籤:vivo 模式 知識 font 最好 設定 reads 為什麼 對比
1.前言
垃圾收集器是前一章垃圾收集演算法理論知識的具體實現了,不同虛擬機器所提供的垃圾收集器可能會有很大差別,另外我們必須提前說明一個道理:沒有最好的垃圾收集器,更加沒有萬能的收集器,只能選擇對具體應用最合適的收集器。這也是HotSpot為什麼要實現這麼多收集器的原因,下面我們以HotSpot為例講解。在寫之前,先介紹幾個概念。
1.1.並行和並發的區別
這個區別之前在你專門的一節介紹過,這裡再重點提一下:這兩個名詞都是並發編程中的概念,在談論垃圾收集器的上下文語境中,可以這麼理解這兩個名詞:
1、並行Parallel
多條垃圾收集線程並行工作,但此時使用者線程仍然處於等待狀態。
2、並發Concurrent
指使用者線程與垃圾收集線程同時執行(但並不一定是並行的,可能會交替執行),使用者程式在繼續運行,而垃圾收集程式運行於另一個CPU上。
1.2.Minor GC和Full GC的區別
-
新生代GC(Minor GC):指發生在新生代的垃圾收集動作,因為Java對象大多都具備朝生夕滅的特性(存活率不高),所以Minor GC非常頻繁,一般回收速度也比較快。
-
老年代GC(Major GC / Full GC):指發生在老年代的垃圾收集動作,出現了Major GC,經常會伴隨至少一次的Minor GC(但非絕對的,在Parallel Scavenge收集器的收集策略裡就有直接進行Major GC的策略選擇過程)。Major GC的速度一般會比Minor GC慢10倍以上。
1.3.輸送量
輸送量:就是CPU用於運行使用者代碼的時間與CPU總消耗時間的比值,即輸送量 = 運行使用者代碼時間 /(運行使用者代碼時間 + 垃圾收集時間)。虛擬機器總共運行了100分鐘,其中垃圾收集花掉1分鐘,那輸送量就是99%。
2.垃圾收集器組合
下面一張圖是HotSpot虛擬機器包含的所有收集器:
(A):圖中展示了7種不同分代的收集器:
Serial、ParNew、Parallel Scavenge、Serial Old、Parallel Old、CMS、G1;
(B):而它們所處地區,則表明其是屬於新生代收集器還是老年代收集器:
新生代收集器:Serial、ParNew、Parallel Scavenge;
老年代收集器:Serial Old、Parallel Old、CMS;
整堆收集器:G1;
(C):兩個收集器間有連線,表明它們可以搭配使用:
Serial/Serial Old、Serial/CMS、ParNew/Serial Old、ParNew/CMS、Parallel Scavenge/Serial Old、Parallel Scavenge/Parallel Old、G1;
(D):其中Serial Old作為CMS出現"Concurrent Mode Failure"失敗的後備預案(後面介紹);
2.1 Serial收集器
-
特性:
最基本、發展曆史最久的收集器,採用複製演算法的單線程收集器,單線程一方面意味著它只會使用一個CPU或一條線程去完成垃圾收集工作,另一方面也意味著在它進行垃圾收集時,必須暫停其他所有的背景工作執行緒,直到它收集結束為止,這個過程也稱為 Stop The world。後者意味著,在使用者不可見的情況下要把使用者正常工作的線程全部停掉,這顯然對很多應用是難以接受的。
-
應用情境:
Serial收集器依然是虛擬機器運行在Client模式下的預設新生代收集器。 在使用者的案頭應用情境中,可用記憶體一般不大(幾十M至一兩百M),可以在較短時間內完成垃圾收集(幾十MS至一百多MS),只要不頻繁發生,這是可以接受的
-
優勢:
簡單而高效(與其他收集器的單線程相比),對於限定單個CPU的環境來說,Serial收集器由於沒有線程互動的開銷,專心做垃圾收集自然可以獲得最高的單線程收集效率。比如在使用者的案頭應用情境中,可用記憶體一般不大(幾十M至一兩百M),可以在較短時間內完成垃圾收集(幾十MS至一百多MS),只要不頻繁發生,這是可以接受的。
Stop TheWorld 說明:
GC在後台自動發起和自動完成的,在使用者不可見的情況下,把使用者正常的背景工作執行緒全部停掉,即GC停頓,會帶給使用者不良的體驗;
從JDK1.3到現在,從Serial收集器-》Parallel收集器-》CMS-》G1,使用者線程停頓時間不斷縮短,但仍然無法完全消除;
設定參數
"-XX:+UseSerialGC":添加該參數來顯式的使用串列垃圾收集器;
Serial/Serial Old組合收集器運行如下:
2.2 ParNew收集器
- 特性:
ParNew收集器其實就是Serial收集器的多線程版本,除了使用多條線程進行垃圾收集外,其餘行為和Serial收集器完全一樣,包括Serial收集器可用的所有控制參數、收集演算法、Stop The world、對象分配規則、回收策略等都一樣。在實現上也共用了相當多的代碼。
-
應用情境:
ParNew收集器是許多運行在Server模式下的虛擬機器中首選的新生代收集器。很重要的原因是:除了Serial收集器之外,目前只有它能與CMS收集器配合工作(看圖)。在JDK1.5時期,HotSpot推出了一款幾乎可以認為具有劃時代意義的垃圾收集器-----CMS收集器,這款收集器是HotSpot虛擬機器中第一款真正意義上的並發收集器,它第一次實現了讓垃圾收集線程與使用者線程同時工作。
-
優勢:
在單CPU中的環境中,不會比Serail收集器有更好的效果,因為存線上程互動開銷,甚至由於線程互動的開銷,該收集器在兩個CPU的環境中都不能百分百保證可以超越Serial收集器。當然,隨著可用CPU數量的增加,它對於GC時系統資源的有效利用還是很有好處的,它預設開啟的收集線程數與CPU數量相同。
設定參數:
"-XX:+UseConcMarkSweepGC":指定使用CMS後,會預設使用ParNew作為新生代收集器;
"-XX:+UseParNewGC":強制指定使用ParNew;
"-XX:ParallelGCThreads":指定垃圾收集的線程數量,ParNew預設開啟的收集線程與CPU的數量相同;
ParNew/Serial Old組合收集器運行如下:
2.3 Parallel Scavenge 收集器
- 特性:
Parallel Scavenge收集器是一個新生代收集器,它也是使用複製演算法的收集器,也是並行的多線程收集器。
-
對比分析:
-
Parallel Scavenge收集器 VS CMS等收集器:
Parallel Scavenge收集器的特點是它的關注點與其他收集器不同,CMS等收集器的關注點是儘可能地縮短垃圾收集時使用者線程的停頓時間,而Parallel Scavenge收集器的目標則是達到一個可控制的輸送量(Throughput)。
由於與輸送量關係密切,Parallel Scavenge收集器也經常稱為“輸送量優先”收集器。
-
Parallel Scavenge收集器 VS ParNew收集器:
Parallel Scavenge收集器與ParNew收集器的一個重要區別是它具有自適應調節策略。
-
應用情境:
Parallel Scavenge收集器是虛擬機器運行在Server模式下的預設垃圾收集器。
停頓時間短適合需要與使用者互動的程式,良好的響應速度能提升使用者體驗;高輸送量則可以高效率利用CPU時間,儘快完成運算任務,主要適合在後台運算而不需要太多互動的任務。
該收集器以高輸送量為目標,就是減少垃圾收集時間,從而讓使用者代碼獲得更長的已耗用時間。所以適合那些運行在多個CPU上,並且專註於後台計算的應用程式,例如:執行批量處理任務、訂單處理,工資支付,科學計算等。
設定參數:
虛擬機器提供了-XX:MaxGCPauseMillis和-XX:GCTimeRatio兩個參數來精確控制最大垃圾收集停頓時間和輸送量大小。不過不要以為前者越小越好,GC停頓時間的縮短是以犧牲輸送量和新生代空間換取的。
"-XX:+MaxGCPauseMillis":控制最大垃圾收集停頓時間,大於0的毫秒數;這個參數設定的越小,停頓時間可能會縮短,但也會導致輸送量下降,導致垃圾收集發生得更頻繁。
"-XX:GCTimeRatio":設定垃圾收集時間佔總時間的比率,0<n<100的整數,就相當於設定輸送量的大小。
垃圾收集執行時間占應用程式執行時間的比例的計算方法是:
1 / (1 + n)
例如,選項-XX:GCTimeRatio=19,設定了垃圾收集時間佔總時間的5%--1/(1+19);
預設值是1%--1/(1+99),即n=99;
垃圾收集所花費的時間是年輕一代和老年代收集的總時間;
GC自適應的調節策略:
Parallel Scavenge收集器有一個參數-XX:+UseAdaptiveSizePolicy。當這個參數開啟之後,就不需要手工指定新生代的大小、Eden與Survivor區的比例、晉陞老年代對象年齡等細節參數了,虛擬機器會根據當前系統的運行情況收集效能監控資訊,動態調整這些參數以提供最合適的停頓時間或者最大的輸送量,這種調節方式稱為GC自適應的調節策略(GC Ergonomics)。如果對於垃圾收集器運作原理不太瞭解,以至於在最佳化比較困難的時候,使用Parallel收集器配合自適應調節策略,把記憶體管理的調優任務交給虛擬機器去完成將是一個不錯的選擇。
Java虛擬機器9:垃圾收集(GC)-4(垃圾收集器)