Incremental,Generational, Mostly-Copying Garbage Collection in

Incremental,Generational,
Mostly-Copying Garbage Collection
in Uncooperative Environments
by G.May Yip, A Master Thesis, MIT, 1991
について。
発表者: 小林 義徳
http://www.research.compaq.com/wrl/techreports/abstracts/91.8.html
About this GC…

Incremental, generational
mostly-copying garbage collector for C++

Uniprocessor
特別な hardware サポートなしで動作。
コンパイラへの変更も不要
UNIXの mprotect システムコールを使用



The collector achieves…
GC 一回あたりの停止時間が短い
(from incremental collection)
 トータルのGC 時間もそれほど長くない
(from generational collection)
 ハードウェアやコンパイラのサポートなしで
動作
(from mostly-copying collection)

内容
Generational GC
 Program Interface in C++
 Bartlett’s Generational MostlyCopying Collector
 Incremental,Generational
Mostly-Copying Collection
詳細
実験結果
今後の課題

Generational GC

経験則:
ほとんどのオブジェクトは生成後すぐにゴミになり、
ある程度の期間以上生き残ったオブジェクトはさらに長期に
わたって生き残る

一定回数以上の GC で生き残ったオブジェクトを古いオブジェ
クトとみなす。
GC の際、古いオブジェクトは、最初から生きているとして扱う。
結果として、GC の仕事を減らすことができる


Generational GC(図)
Old space
Remembered set
New space
stack,registers,static area
Generational GC


Root set は、スタック、レジスタ、スタティック領域の変数の
ほかに、 remembered set も用いる
remembered set
= 新しいオブジェクトを指す古いオブジェクト全体を含む集合
(Bartlett’s GC や this GC では,
the remembered set = 古いオブジェクト全体)
Program Interface in C++
struct word{
word *lesser,*greater;
・・・
GCCLASS(word);
クラス word はGC によって回収される
}
word::word(char* chars){
GCALLOCV(word,sizeof(word) + strlen(chars));
・・・
可変サイズのクラスはGCALLOCV で allocate
}
void word::GCPointers(){
オブジェクト内のポインタを扱うため
のgcpointer(lesser);
CALLBACK
gcpointer(greater);
}
Rules



class C:P{} について、
C::GCPointers() 内に P::GCPointers()を書く
class C { X x;} について、
C::GCPointers() 内に x.GCPointers() を書く
class C { X* x;} について、
C::GCPointers() 内に gcpointer(x) を書く
GCCLASS(word) および
gcpointer(x)

マクロ GCCLASS(word)



インライン関数 gcpointer(x)


コールバック word::GCPointers() を宣言している。
new 演算子をオーバーロードし、その中でコールバック
word::GCPointers のGC への登録を行っている。
x = gcmove(x) のように展開される。
GC 時には、word::GCPointers() が呼び出され、
word 内のポインタが指すオブジェクトをコピー。
Bartlett’s Mostly-Copying
Collector[1][2]

Compacting,conservative collector
スタックやレジスタ内の word については、
すべてポインタとして扱う。
 ヒープ内に確保されるオブジェクトの構造に
ついては、知っているものとする。
 コンパイラのサポートが不要

Allocation

2-level allocation
 small objects (1ページよりも小さいオブジェクト)
1. heap page を一つ確保
2. heap page よりオブジェクトを確保
 large objects (一ページよりも大きいオブジェクト)
1. 十分な量のページを確保
ページの最後の余った部分は使われない
Spaces

heap page (512 bytes/page) について
 space identifier : an integer
current-space , next-space (later)
 type identifier : OBJECT or CONTINUED
小さいオブジェクトをもっているページ
: OBJECT
大きいオブジェクト(1ページ以上)
最初のページ
: OBJECT
残りのページ
: CONTINUED
Two Spaces

current-space
新しいオブジェクトは current-space より確保
Copy GC の from-space に対応

next-space
Root pointer に指されたオブジェクトをもつページ
GC により動かされたオブジェクトをもつページ
Copy GC の to-space に対応
Space ID を管理する変数
curr_space : current-space の space ID
next_space : next-space の space ID
 初期設定
curr_space = next_space = 3;
 GC が走っていないとき
curr_space == next_space
 GC の最中
curr_space != next_space
Heap Spaces (Normally)
ID = 3
ID = 3
ID = 3
ID = 3
ID = 3
ID = 3
ID = 3
ID = 3
curr_space = next_space = 3
Allocation
GC が走っていない間
オブジェクトは current-space より確保
(curr_space = next_space)
 GC の最中
オブジェクトをコピーするためのスペースは
next-space より確保

Collection(1)

allocatedpages >= heappages /2
となった時点でGC が起動される。
1.
next_space = curr_space + 1;
Root set を探索
(スタック、レジスタ、static 領域の変数、
remembered set)
‘root pointers’ に「指されている」 currentspace を promote
(promote : spaceID = next_space)
2.
3.
Collection(2)
4.
5.
古いオブジェクトおよび promote された
ページより、オブジェクトを探索・コピー
(幅優先探索)
curr_space = curr_space + 2;
next_space = curr_space;
Heap Spaces (Before GC)
Root set
ID = 3
ID = 3
ID = 3
ID = 3
curr_space = next_space = 3
Heap Spaces (Start GC)
Root set
ID = 4
ID = 4
ID = 3
ID = 3
curr_space = 3 , next_space = 4
(next_space++)
Heap Spaces (During
GC(1))
Root set
ID = 4
ID = 4
ID = 3
ID = 3
curr_space = 3 , next_space = 4
Forwarding pointer
Heap Spaces (During
GC(2))
Root set
ID = 4
ID = 4
ID = 3
ID = 3
curr_space = 3 , next_space = 4
Forwarding pointer
Heap Spaces (During
GC(3))
Root set
ID = 4
ID = 4
ID = 3
ID = 3
curr_space = 3 , next_space = 4
Forwarding pointer
Heap Spaces (After GC)
Root set
ID = 4
ID = 4
ID = 5
ID = 5
curr_space = next_space = 5
(curr_space +=2,next_space++)
Picking Up Generations[2]




一度でも GC を生き残ったオブジェクトを古いオブ
ジェクトとみなす。
GC後、古いオブジェクトを持つページは、偶数の
space identifier をもつ。
GC は、古いオブジェクト全体を remembered set
として扱う。
たまには、古いオブジェクトも回収(major
collection)

minor collection 後、古いオブジェクトがヒープの 85 % を超えてい
たとき、Mark-Compact GC を実行[3]
Incremental,Generational
Mostly-Copying Collector

Incremental Collector




アプリケーションの動作の合間に細切れにGarbage
Collection を行う。GC をすこし行ったら、アプリケーションに
制御を返してしまう。
一度のGC の停止時間は短いが、totalのGC時間は長くなる
ページ保護を用い、Page Faultの際に少しずつ探索と Copy
を行う。(mprotect を用いて、read/write protect)
Generational Collector


通常は、新しいオブジェクトのみを対象に GC を行う。
Total のGC 時間を減らすことができる。
3-space strategy

current-space (変数 curr_space)
新しいオブジェクトは、current-space より確保

previous-space (prev_space)
GC の最中で、未探索のページ

forward-space (forw_space)
Root pointer に指されているページ
オブジェクトのコピー用のメモリは forward-space より確保
Bartlett’s GC の next-space に相当
GC が走っていない間は、これら3つの space の区別はない。
cf.2-spaces in Bartlett’s GC

current-space
新しいオブジェクトは current-space より確保
Copy GC の from-space に対応

next-space
Root pointer に指されたオブジェクトをもつページ
GC により動かされたオブジェクトをもつページ
Copy GC の to-space に対応
GC を開始するタイミング

GC を開始するタイミング


allocatedpages >= heappages /3
GC を再開するタイミング


保護されたページへのアクセスがあったとき
アプリケーションが新しい heap page を確保したとき。
保護されたページをランダムに選び、GC を行う。
Start GC
1.
space-ID を管理する変数を更新
(forw_space,prev_space,curr_space)
2.
3.
Root set を探索
root pointer に指されているpages を promote
(Promote : space-ID = forw_space)
4.
古いオブジェクトをもつページと 3. のページを保護
(mprotect
5.
: read/write protect)
アプリケーションに制御を返す
Start GC
curr_space
protected pages
unprotected pages
A
Root set
forw_space = curr_space
B
= prev_space
C
prev_space = curr_space
D
curr_space
forw_space = curr_space + 1;
curr_space
= curr_space + 2;
Protect Pages(1)
forw_space
protected pages
unprotected pages
A
Root set
B
C
D
prev_space
Trap Handler’s Works
(During GC)
1.
2.
3.
4.

Page Fault の起こったページの保護を外す
ページ内のオブジェクトを探索・コピー
2.でコピーされたオブジェクトを含むページを保護
(Protect : neither readable nor writable)
アプリケーションに制御を返す。
アプリケーションが新しい heap page を確保する際、
保護されたページをランダムに選び、scan を行う。
Handle Page Fault(1)
forw_space
B’
C’
A
forw_space
B
C
protected pages
unprotected pages
forwarding pointers
D
prev_space
Handler Protects Pages(2)
forw_space
B’
C’
A
forw_space
B
C
protected pages
unprotected pages
forwarding pointers
D
prev_space
Handle Page Fault(2)
forw_space
B’
C’
A
forw_space
B
C
D’
D
prev_space
forw_space
Handler Protects Pages(3)
forw_space
B’
C’
A
forw_space
B
C
D’
D
prev_space
forw_space
Handle Page Fault(3)
forw_space
B’
C’
A
forw_space
All protected pages
have been
unprotected and
scanned
D’
forw_space
Finish GC

保護されたページがなくなった時点で、GC 終了

Space-ID 変数を更新
prev_space = forw_space = curr_space
(At the start of GC,
prev_space = curr_space
forw_space = curr_space + 1;
curr_space

= curr_space + 2;)
最後まで prev_space だったページはGC 後、
再利用可能になる。
Benchmark Program

words
テキストファイルを読み、その中の単語について、
辞書順のbinary tree を生成するプログラム。

bipsctrl
WRL で作られた CAD system の一部
実験結果

Non-Incremental Generational
V.S. Incremental Generational
別紙の実験結果によると、
Incremental 化による GC 処理時間の増加は、
words
で 24 %,
bipsctrl で
にとどまっている。
7%
Real-Time Performance
使用したベンチマークプログラムについて、
平均の GC の停止時間は、約 4msec ほど
であった。
 最大の停止時間も、せいぜい 100 msec 以
内に収まった

まとめ

Bartlett のGenerational Mostly-Copying
GC が Incremental化された。
previous-space の概念を追加
 mprotect によるページ保護


Performance もそれなりによかった
最大の停止時間も 100msec 以下に抑えられた。
 Total のGC 時間もそれほど大きくならなかった。

Future Works

Non-concurrent collector
concurrent collector

GC の初期化プロセスも incremental 化
GC 初期化処理による停止時間が一番長い
 GC 初期化時間は、root set の大きさに比例。

References
[1] Joel F.Bartlett,1988
Compacting Garbage Collection with Ambiguous Roots
[2] Joel F.Bartlett,1989
Mostly-Copying Garbage Collection Picks Up Generations and
C++
[3] Richard Jones and Rafael Lins,1996
Garbage Collection,Algorithm for Automatic Dynamic Memory
Management
References
[4] 遠藤 敏夫,1999
一般教養としての Garbage Collection