本文主要研究一下ShenandoahGC的Brooks Pointershtml
Shenandoah面向low-pause-time的垃圾收集器,它的GC cycle主要有less
包括Init Mark(Pause)、Concurrent Mark、Final Mark(Pause)
這個階段用到了Brooks Pointers(
object version change with additional atomically changed indirection)進行copy
)包括Init update Refs(Pause)、Concurrent update Refs、Final update Refs(Pause)
其中Final Mark或者Final update Refs以後均可能進行Concurrent cleanup,進行垃圾回收,reclaims region
G1 GC在evacuation階段是parallel的,但不是concurrent,ShenandoahGC爲了作到concurrent copy使用了Brooks Pointers。wordpress
Rodney A. Brooks在<<Trading Data Space for Reduced Time and Code Space in Real-Time Garbage Collection on Stock Hardware>>這篇論文提出了一種使用forwarding pointer來作到concurrent copy的方案,該方案在全部對象的內存結構上新增一個forwarding pointer,它要麼指向對象本身,要麼指向在to-region的本身的拷貝
其要點以下:atom
若是在evacuation期間,其餘線程經過舊的引用訪問到了from-region的舊對象,它就須要根據舊對象的forwarding pointer找到to-region的拷貝對象;等全部舊對象的引用都更新完以後,後續就能夠回收from-region的舊對象
class VersionUpdater<T, V> { final AtomicReference<T> ref = ...; void writeValue(V value) { do { T oldObj = ref.get(); T newObj = copy(oldObj); newObj.set(value); } while (!ref.compareAndSet(oldObj, newObj)); } }
這裏使用do while循環,即先拷貝再進行CAS,若是CAS不成功則繼續嘗試拷貝和CAS
stub Write(val, obj, offset) { if (evac-in-progress && // in evacuation phase in-collection-set(obj) && // target is in from-space fwd-ptrs-to-self(obj)) { // no copy yet val copy = copy(obj); *(copy + offset) = val; // actual write if (CAS(fwd-ptr-addr(obj), obj, copy)) { return; // success! } } obj = fwd-ptr(obj); // write to actual copy *(obj + offset) = val; // actual write }
在evacuation階段,對from-region的對象的寫操做會觸發該對象的evacuation操做(
若是該對象在to-region尚未copy的話
)
stub evacuate(obj) { if (in-collection-set(obj) && // target is in from-space fwd-ptrs-to-self(obj)) { // no copy yet copy = copy(obj); CAS(fwd-ptr-addr(obj), obj, copy); } }
evacuate先判斷該對象是否在from-region且在to-region尚未copy,若是知足條件則進行拷貝,而後CAS修改舊對象的forwarding pointer指向拷貝對象
object version change with additional atomically changed indirection
)進行copy,以實現concurrent copy