聊聊ShenandoahGC的Brooks Pointers

本文主要研究一下ShenandoahGC的Brooks Pointershtml

Shenandoah

Shenandoah面向low-pause-time的垃圾收集器,它的GC cycle主要有bash

  • Snapshot-at-the-beginning concurrent mark包括Init Mark(Pause)、Concurrent Mark、Final Mark(Pause)
  • Concurrent evacuation(這個階段用到了Brooks Pointers(object version change with additional atomically changed indirection)進行copy)
  • Concurrent update references (optional)包括Init update Refs(Pause)、Concurrent update Refs、Final update Refs(Pause)

其中Final Mark或者Final update Refs以後均可能進行Concurrent cleanup,進行垃圾回收,reclaims regionless

Brooks Pointers

G1 GC在evacuation階段是parallel的,但不是concurrent,ShenandoahGC爲了作到concurrent copy使用了Brooks Pointers。wordpress

Rodney A. Brooks在<>這篇論文提出了一種使用forwarding pointer來作到concurrent copy的方案,該方案在全部對象的內存結構上新增一個forwarding pointer,它要麼指向對象本身,要麼指向在to-region的本身的拷貝ui

其要點以下:atom

  • evacuation的第一步是拷貝from-region的對象到to-region
  • evacuation的第二步使用CAS改變from-region的對象的forwarding pointer由本身變爲指向to-region的拷貝對象
  • evacuation的第三步就是遍歷heap,更新引用到to-region的拷貝對象

若是在evacuation期間,其餘線程經過舊的引用訪問到了from-region的舊對象,它就須要根據舊對象的forwarding pointer找到to-region的拷貝對象;等全部舊對象的引用都更新完以後,後續就能夠回收from-region的舊對象spa

示例代碼

concurrent copy

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.net

write barriers

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的話)線程

evacuation

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指向拷貝對象code

小結

  • Shenandoah面向low-pause-time的垃圾收集器,它在Concurrent evacuation階段用到了Brooks Pointers(object version change with additional atomically changed indirection)進行copy,以實現concurrent copy
  • Rodney A. Brooks在<>這篇論文提出了一種使用forwarding pointer來作到concurrent copy的方案,該方案在全部對象的內存結構上新增一個forwarding pointer,它要麼指向對象本身,要麼指向在to-region的本身的拷貝
  • evacuation的第一步是拷貝from-region的對象到to-region;evacuation的第二步使用CAS改變from-region的對象的forwarding pointer由本身變爲指向to-region的拷貝對象;evacuation的第三步就是遍歷heap,更新引用到to-region的拷貝對象

doc

相關文章
相關標籤/搜索