PSYoungGen ParNewGeneration DefNewGeneration等名詞解釋
簡單來說,有這麼多東西反映了HotSpot VM的開發歷史和實現細節。我在寫篇東西講述這部分歷史,哪天寫完的話在這邊也放個連結嗯。
DefNewGeneration是default new generation
ParNewGeneration是parallel new generation
原本HotSpot VM裡沒有並行GC,當時就只有NewGeneration;後來準備要加入young gen的並行GC,就把原本的NewGeneration改名為DefNewGeneration,然後把新加的並行版叫做ParNewGeneration。
這些XXXGeneration都在HotSpot VM的“分代式GC框架”內。本來HotSpot VM鼓勵開發者儘量在這個框架內開發GC,但後來有個開發就是不願意被這框架憋著,自己硬寫了個沒用寫框架的新並行GC,並拉攏效能測試團隊用這個並行GC來跑分,成績也還不錯,於是這個GC就放進HotSpot VM裡了。這就是我們現在看到的ParallelScavenge。
(結果就是HotSpot GC組不得不維護兩個功能幾乎一樣的並行GC。其實是件很頭疼的事情嗯)
Scavenge或者叫scavenging GC,其實就是copying GC的另一種叫法而已。HotSpot VM裡的GC都是在minor GC收集器裡用scavenging的,DefNew、ParNew和ParallelScavenge都是,只不過DefNew是序列的copying GC,而後兩者是並行的copying GC。
由此名字就可以知道,“ParallelScavenge”的初衷就是把“scavenge”給並行化。換句話說就是把minor GC並行化。至於full GC,那不是當初關注的重點。
把GC並行化的目的是想提高GC速度,也就是提高吞吐量(throughput)。所以其實ParNew與ParallelScavenge都可叫做Throughput GC。
但是在HotSpot VM的術語裡“Throughput GC”通常特指“ParallelScavenge”。
================================
ParallelScavenge和ParNew都是並行GC,主要是並行收集young gen,目的和效能其實都差不多。最明顯的區別有下面幾點:
1、PS以前是廣度優先順序來遍歷物件圖的,JDK6的時候改為預設用深度優先順序遍歷,並留有一個UseDepthFirstScavengeOrder引數來選擇是用深度還是廣度優先。在JDK6u18之後這個引數被去掉,PS變為只用深度優先遍歷。ParNew則是一直都只用廣度優先順序來遍歷
2、PS完整實現了adaptive size policy,而ParNew及“分代式GC框架”內的其它GC都沒有實現完
3、由於在“分代式GC框架”內,ParNew可以跟CMS搭配使用,而ParallelScavenge不能。當時ParNew GC被從Exact VM移植到HotSpot VM的最大原因就是為了跟CMS搭配使用。
================================
還有一點要注意:上面說ParallelScavenge並行收集young gen,那old/perm gen呢?
其實最初的ParallelScavenge的目標只是並行收集young gen,而full GC的實際實現還是跟serial GC一樣。只不過因為它沒有用HotSpot VM的generational GC framework,自己實現了一個CollectedHeap的子類ParallelScavengeHeap,裡面都弄了獨立的一套介面,而跟HotSpot當時其它幾個GC不相容。其實真的有用的程式碼大部分就在PSScavenge(=“ParallelScavenge的Scavenge”)裡,也就是負責minor GC的收集器;而負責full GC的收集器叫做PSMarkSweep(=“ParallelScavenge的MarkSweep”),其實只是在serial GC的核心外面套了層皮而已,骨子裡是一樣的LISP2演算法的mark-compact收集器(別被名字騙了,它並不是一個mark-sweep收集器)。
當啟用-XX:+UseParallelGC時,用的就是PSScavenge+PSMarkSweep的組合。
這是名副其實的“ParallelScavenge”——只並行化了“scavenge”。
所以其實非要說對應關係的話,PSScavenge才是真的跟ParNew對等的東西;ParallelScavenge這個名字既指代整套新GC,也可指代其真正賣點的PSScavenge。
不知道後來什麼原因導致full GC的並行化並沒有在原本的generational GC framework上進行,而只在ParallelScavenge繫上進行了。其成果就是使用了LISP2演算法的並行版的full GC收集器,名為PSCompact(=“ParallelScavenge-MarkCompact”),收集整個GC堆。
當啟用-XX:+UseParallelOldGC時,用的就是PSScavenge+PSCompact的組合。
此時ParallelScavenge其實已經名不符實了——它不只並行化了“scavenge”(minor GC),也並行化了“mark-compact”(full GC)。