More Related Content
Similar to Precise garbage collection for c (20)
Precise garbage collection for c
- 2. Precise Garbage Collection for C
著者
Jon Rafkind, Adam Wick, John Regehr, Matthew Flatt
入手先
http://www.cs.utah.edu/~regehr/papers/ismm15-rafkind.pdf
- 4. PLT Schemeにあった怖い話
• PLT Schemeを使用したプログラム環境
DrSchemeは毎日再起動をしなければならなかっ
た。でも、正確なGCに変えたら再起動が必要なく
なった
• バイトコードとドキュメントを生成すると、正確な
GCだと200MBで済むところが、保守的GCだと
700MBも必要だった
• PLT Schemeで作ったmail clientを1日おきに再起
動していたが、正確なGCに変えたら再起動しなく
て済むようになった
- 5. 正確なGCを実現するためには
• 次の2つが重要
– 生きているポインタとそうでないものを分ける
– アロケーションしたものとその中身がなんなのかをしっ
かり関連付ける
• 簡単に言うけど難しいよーだってCだもん
– コンパイラ相当のものを作って、もってる型情報とか
駆使して頑張る
- 7. サポートしていません
• いったん、範囲外にポインタを動かしてもう一度
範囲内に戻す
p = malloc(1024)
p -= 1024
p[1025] /* access 1024 to 2047 */
• ポインタでxorをとってみたり
– xor linked listとか。頭いい人っているねー
• 一旦整数にcastしてまたポインタにcast
– CRubyはgive up
• ライブラリの中でアロケーションしちゃったりとか
- 8. ローカル変数
ポインタの情報を配列に入れる // TRANSFORMED
int cheeseburger(int* x) {
void* gc_stack_frame[3];
→ プログラム変換を行う /* chain to previous frame: */
void* last_stack_frame = GC_last_stack_frame();
gc_stack_frame[0] = last_stack_frame;
/* number of elements + shape category: */
gc_stack_frame[1] = (1 << 2) + GC_POINTER_TYPE;
/* variable address: */
// ORIGINAL
gc_stack_frame[2] = &x;
int cheeseburger(int* x) { /* install frame: */
GC_set_stack_frame(gc_stack_frame);
add_cheese(x);
add_cheese(x);
return x[17]; /* restore old GC frame */
GC_set_stack_frame(last_stack_frame);
}
return x[17];
}
- 9. 変換後プログラム拡大
// TRANSFORMED /* variable address: */
int cheeseburger(int* x) { gc_stack_frame[2] = &x;
void* gc_stack_frame[3]; /* install frame: */
GC_set_stack_frame(gc_stack_frame);
/* chain to previous frame: */
add_cheese(x);
void* last_stack_frame =
GC_last_stack_frame(); /* restore old GC frame */
gc_stack_frame[0] = last_stack_frame; GC_set_stack_frame(last_stack_frame);
return x[17];
/* number of elements + shape category:
*/ }
gc_stack_frame[1] = (1 << 2) +
GC_POINTER_TYPE;
- 11. malloc部分の変換
• mallocってこんな感じで使うよね
malloc(sizeof(foo) * 5)
• これをみると、アロケーションするタイプ
(foo)と数(5)が分かるわけだ。
• 正確なGCだと何の型のデータをアロケーションしたかの
情報も必要なのでこんな感じで変換
GC_malloc(sizeof(foo) * 5, gc_foo_tag)
• で、foo_tagってなんなの?
– それは次のスライドの心だー
- 12. gc_foo_tagって?
• gc_tag_struct型の構造体
• アローケートしたオブジェクトと型を結びつける
• 内容はmarkとrepair(コンパクション) 処理を行う
関数へのポインタ
struct foo { int *x; int *y;} とするとmarkを行う関数
void gc_mark_struct_foo (void * x_) {
struct foo *tmp = (struct foo *) x_;
GC_mark(tmp->x);
GC_mark(tmp->y);
}
こんな関数をコンパイル時に自動生成する。
ユーザがmark/repair関数をカスタマイズすることも可能
- 13. いろいろやってみた
(PTL Scheme)
• PLT SchemeのGCをConservative GCから
Precise GCにしてみた
• 最初に説明した通り、メモリ使用量が激減
• 実行速度は
– メモリアロケーションが多いベンチマークは20%
くらい速くなる
– メモリアロケーションが少ないベンチマークは1
0~20 %遅くなる
- 14. いろいろやってみた
(Linuxカーネル!)
• カーネルなんて絶対メモリーリークしちゃい
かんし、GCが欲しいよね
• なんかいろいろ面倒だったみたい。続きは
論文で
• tmpfsからddコマンドでファイルアクセス
– GC付きのものが4割ほど遅い
• HDDからddコマンドでファイルアクセス
– あまり変わらない
- 15. まとめ
• この技術すげー。今後、いろんなところで
使われるようになるはず。
• GC本第2版は保守的GCの章を書き換えな
いといかんかもしれませんねー
• 8ccでサポート予定だから楽しみ
http://github.com/rui314/8cc