我們的垃圾收集器
(譯者注:這篇博文發表在2008年,雖然年代有些久遠,但是文中說到的垃圾收集器我們至今還在使用,作者也談到了對於G1垃圾收集器的期望。)
最近我在白板上給客戶化了一個圖表,他們似乎對這個有點興趣,所以我想我可以重畫一遍來給你們消遣。
每個藍色的盒子都代表了一個收集器,用來收集某一代。黃色區域中的藍色盒子是用來收集新生代的,灰色區域中的藍色盒子是用來收集老年代的。
- Serial”是一個單線程、stop-the-world、使用複製算法的收集器。
- “ParNew” 是一個多線程、stop-the-world、使用複製算法的收集器。和”Parallel Scavenge”不同,它可以和”CMS”收集器一起使用。比如說,”ParNew”做了同步需要,以便它能在CMS的並發階段繼續運行。
- “Parallel Scavenge” 是一個多線程、stop-the-world、複製算法的收集器。
- “Serial Old”是一個單線程 、stop-the-world、使用標記-清除-壓縮的收集器。
- “CMS”是一個並發、短暫停的收集器。
- “Parallel Old”是多線程、使用壓縮算法的收集器。
對於JDK6,可以使用-XX來標記我們的收集器。
- UseSerialGC 是”Serial”+”Serial Old”
- UseParNewGC 是”ParNew”+”Serial Old”
- UseConcMarkSweepGC 是”ParNew”+”CMS”+”Serial Old”。大多數時候是使用”CMS”來手機老年代,當並發模式失敗的時候使用”Serial Old”
- UseParallelGC 是”Parallel Scavenge”+”Serial Old”
- “CMS”是一個並發、短暫停的收集器。
- UseParallelOldGC 是”Parallel Scavenge”+”Parallel Old”
FAQ
1.UseParallelGC 和UseParNewGC 都是多線程來收集新生代,哪個更快?
這個問題沒有準確的答案。大部分他們性能相當,但是我還是見過在不同的情景下其中一個比另一個更好。
2.為什麼”ParNew”和”Parallel Old”不能同時運行?
在”ParNew” 的風格下,每個被收集的代對於它的收集都提供一個確定的接口,比如說,”ParNew”實現了 space_iterate()方法,這個方法將對新生代中的每個對象應用一個操作。當使用”CMS” 或”Serial Old” 收集老年代的時候。GC可以使用 space_iterate() 來對在新生代中的的對象進行操作。這讓收集器可以混合工作,但是會造成收集器維持的一些負擔。並且這個負擔看起來是收集器的二次方。作為一種選擇,”Parallel Scavenge”總是知道老年代是怎麼收集的,並且能直接調用在”Serial Old” 收集器中的代碼。”Parallel Old”不是”ParNew”風格的,所以不會和”ParNew”匹配。順便說一下,我們希望最終隻有”Parallel Scavenge”和”Parallel Old”可以進行匹配。
對於我上麵的使用的例子,不要想太多。他們就是這樣設計的,不要浪費太多時間。
3.怎樣把”Serial”和”CMS”一起使用
使用 -XX:+UseConcMarkSweepGC -XX:-UseParNewGC,而不要使用 -XX:+UseConcMarkSweepGC和 -XX:+UseSerialGC。雖然這樣的組合看起來合乎邏輯,但是這會導致一個信息表示收集器之間有衝突,JVM將不會啟動。
4.上圖中藍色盒子中的問號是不是一個排版錯誤?
這個盒子代表一個正在開發的新的收集器,叫做Garbage First G1收集器。G1將會提供:
- 更加可預測的GC停頓
- 更加高效的GC
- 沒有碎片下更短暫的停頓
- 並行和並發收集器
- 更好的堆利用
G1跨過了新生代和老年代的範圍,因為它是一個隻有邏輯區域的分代收集器。G1把堆劃分為獨立區域,在一次GC中可以收集這片區域的一個子集。它是一個邏輯分代是因為它動態的選擇一片區域作為新生代,這片區域將在下一次GC中被回收。
用戶可以指定一次停頓的目標,G1將會做一個評估(基於過去的收集),評估有多少個區域在這次停頓(停頓目標) 中可以被收集。這片區域被稱之為一個回收集合,G1將在下一次GC中去收集它。
G1能選擇有最多垃圾的區域進行收集(所以叫Garbage First)。
G1采用壓縮算法所以碎片不是問題。為什麼是個問題呢?因為部分填滿的區域會導致內部的碎片。
Java堆沒有被靜態的分為一個新生代和老年代,所以他們尺寸的不平衡在這裏不是問題。
和指定一次停頓時間一起,用戶可以指定一部分花費在GC上的時間(比如說在下一次100秒鍾不要花費超過10秒鍾來進行垃圾收集)。對於這個目標(在100秒內的10秒GC時間),G1能選擇一個回收集合,這個集合是G1預測它能在10秒內收集完的區域。有可能看到一個用戶在下一次收集中指定0秒的垃圾收集時間,但這隻是一個目標,不是一個保證。
如果G1能按我們期待的那樣工作,它將取代 “ParNew” + “CMS”. 成為我們的低停頓收集器。如果你問什麼時候可以準備好G1,請你不要抱怨我的沉默。這是我們團隊最高優先級的工作,但這是一個軟件開發,所以經常會有未知事件。它將在jdk7中推出。對我們而言,越早越好。(譯者注:關於G1的論文發表在2004年,而這篇博客發表在2008年,作者就預料到了不確定性。確實,直到2012年的JDK7u4,Sun公司才認為G1達到了足夠成熟的商用程度,移除了“Experimental”的標識)。
最後更新:2017-05-19 15:02:51