precise garbage collection for c

16

Click here to load reader

Upload: miura1729

Post on 30-Jun-2015

3.414 views

Category:

Documents


3 download

TRANSCRIPT

Page 1: Precise garbage collection for c

Precise Garbage Collection for Cの紹介

CSNagoya 三浦英樹

Page 2: Precise garbage collection for c

Precise Garbage Collection for C

著者

 Jon Rafkind, Adam Wick, John Regehr, Matthew Flatt

入手先http://www.cs.utah.edu/~regehr/papers/ismm15-rafkind.pdf

Page 3: Precise garbage collection for c

CのプログラムでもGC使いたい

• 普通、保守的 GCでしょう

• たとえば、Boehm GCとか

• でも、長い時間使ってるとメモリー使用量がすごく増大する場合があるみたいだよ

• 証拠は?

• それは、次のスライドの心だー

Page 4: Precise garbage collection for c

PLT Schemeにあった怖い話

• PLT Schemeを使用したプログラム環境DrSchemeは毎日再起動をしなければならなかった。でも、正確なGCに変えたら再起動が必要なくなった

• バイトコードとドキュメントを生成すると、正確なGCだと200MBで済むところが、保守的GCだと700MBも必要だった

• PLT Schemeで作ったmail clientを1日おきに再起動していたが、正確なGCに変えたら再起動しなくて済むようになった

Page 5: Precise garbage collection for c

正確なGCを実現するためには

• 次の2つが重要– 生きているポインタとそうでないものを分ける

– アロケーションしたものとその中身がなんなのかをしっかり関連付ける

• 簡単に言うけど難しいよーだってCだもん– コンパイラ相当のものを作って、もってる型情報とか駆使して頑張る

Page 6: Precise garbage collection for c

サポートしています

• 配列なんかの途中を指しているポインタ–効率が悪くなるから出来る限り使わない方がいいみたい

• 共用体–いまどのメンバーを使っているか記録する–代入したメンバーと違うメンバーを使う行儀の悪いことはサポートしない。

Page 7: Precise garbage collection for c

サポートしていません

• いったん、範囲外にポインタを動かしてもう一度範囲内に戻すp = malloc(1024)p -= 1024p[1025] /* access 1024 to 2047 */

• ポインタでxorをとってみたり– xor linked listとか。頭いい人っているねー

• 一旦整数にcastしてまたポインタにcast– CRubyはgive up

• ライブラリの中でアロケーションしちゃったりとか

Page 8: Precise garbage collection for c

ローカル変数

ポインタの情報を配列に入れる

→ プログラム変換を行う

// ORIGINAL

int cheeseburger(int* x) {

add_cheese(x);

return x[17];

}

// 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: */

gc_stack_frame[2] = &x;

/* install frame: */

GC_set_stack_frame(gc_stack_frame);

add_cheese(x);

/* restore old GC frame */

GC_set_stack_frame(last_stack_frame);

return x[17];

}

Page 9: Precise garbage collection for c

変換後プログラム拡大// 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: */

gc_stack_frame[2] = &x;

/* install frame: */

GC_set_stack_frame(gc_stack_frame);

add_cheese(x);

/* restore old GC frame */

GC_set_stack_frame(last_stack_frame);

return x[17];

}

Page 10: Precise garbage collection for c

結局

• GCのシステムにどのローカル変数が生きているポインタを持っているかを教える

– コンパイラが変数の型を把握していることを利用

Page 11: Precise garbage collection for c

 malloc部分の変換

• mallocってこんな感じで使うよねmalloc(sizeof(foo) * 5)

• これをみると、アロケーションするタイプ(foo)と数(5)が分かるわけだ。

• 正確なGCだと何の型のデータをアロケーションしたかの情報も必要なのでこんな感じで変換

 GC_malloc(sizeof(foo) * 5, gc_foo_tag)

• で、foo_tagってなんなの?–それは次のスライドの心だー

Page 12: Precise garbage collection for c

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関数をカスタマイズすることも可能

Page 13: Precise garbage collection for c

いろいろやってみた(PTL Scheme)

• PLT SchemeのGCをConservative GCからPrecise GCにしてみた

• 最初に説明した通り、メモリ使用量が激減

• 実行速度は– メモリアロケーションが多いベンチマークは20%くらい速くなる

– メモリアロケーションが少ないベンチマークは10~20 %遅くなる 

Page 14: Precise garbage collection for c

いろいろやってみた(Linuxカーネル!)

• カーネルなんて絶対メモリーリークしちゃいかんし、GCが欲しいよね

• なんかいろいろ面倒だったみたい。続きは論文で

• tmpfsからddコマンドでファイルアクセス– GC付きのものが4割ほど遅い

•  HDDからddコマンドでファイルアクセス–あまり変わらない

Page 15: Precise garbage collection for c

まとめ

• この技術すげー。今後、いろんなところで使われるようになるはず。

• GC本第2版は保守的GCの章を書き換えないといかんかもしれませんねー

• 8ccでサポート予定だから楽しみ    http://github.com/rui314/8cc

Page 16: Precise garbage collection for c

  ご清聴

ありがとう

ございました