precise garbage collection for c
TRANSCRIPT
![Page 1: Precise garbage collection for c](https://reader038.vdocuments.site/reader038/viewer/2022100603/5592a4561a28ab6e798b45fe/html5/thumbnails/1.jpg)
Precise Garbage Collection for Cの紹介
CSNagoya 三浦英樹
![Page 2: Precise garbage collection for c](https://reader038.vdocuments.site/reader038/viewer/2022100603/5592a4561a28ab6e798b45fe/html5/thumbnails/2.jpg)
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](https://reader038.vdocuments.site/reader038/viewer/2022100603/5592a4561a28ab6e798b45fe/html5/thumbnails/3.jpg)
CのプログラムでもGC使いたい
• 普通、保守的 GCでしょう
• たとえば、Boehm GCとか
• でも、長い時間使ってるとメモリー使用量がすごく増大する場合があるみたいだよ
• 証拠は?
• それは、次のスライドの心だー
![Page 4: Precise garbage collection for c](https://reader038.vdocuments.site/reader038/viewer/2022100603/5592a4561a28ab6e798b45fe/html5/thumbnails/4.jpg)
PLT Schemeにあった怖い話
• PLT Schemeを使用したプログラム環境DrSchemeは毎日再起動をしなければならなかった。でも、正確なGCに変えたら再起動が必要なくなった
• バイトコードとドキュメントを生成すると、正確なGCだと200MBで済むところが、保守的GCだと700MBも必要だった
• PLT Schemeで作ったmail clientを1日おきに再起動していたが、正確なGCに変えたら再起動しなくて済むようになった
![Page 5: Precise garbage collection for c](https://reader038.vdocuments.site/reader038/viewer/2022100603/5592a4561a28ab6e798b45fe/html5/thumbnails/5.jpg)
正確なGCを実現するためには
• 次の2つが重要– 生きているポインタとそうでないものを分ける
– アロケーションしたものとその中身がなんなのかをしっかり関連付ける
• 簡単に言うけど難しいよーだってCだもん– コンパイラ相当のものを作って、もってる型情報とか駆使して頑張る
![Page 6: Precise garbage collection for c](https://reader038.vdocuments.site/reader038/viewer/2022100603/5592a4561a28ab6e798b45fe/html5/thumbnails/6.jpg)
サポートしています
• 配列なんかの途中を指しているポインタ–効率が悪くなるから出来る限り使わない方がいいみたい
• 共用体–いまどのメンバーを使っているか記録する–代入したメンバーと違うメンバーを使う行儀の悪いことはサポートしない。
![Page 7: Precise garbage collection for c](https://reader038.vdocuments.site/reader038/viewer/2022100603/5592a4561a28ab6e798b45fe/html5/thumbnails/7.jpg)
サポートしていません
• いったん、範囲外にポインタを動かしてもう一度範囲内に戻す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](https://reader038.vdocuments.site/reader038/viewer/2022100603/5592a4561a28ab6e798b45fe/html5/thumbnails/8.jpg)
ローカル変数
ポインタの情報を配列に入れる
→ プログラム変換を行う
// 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](https://reader038.vdocuments.site/reader038/viewer/2022100603/5592a4561a28ab6e798b45fe/html5/thumbnails/9.jpg)
変換後プログラム拡大// 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](https://reader038.vdocuments.site/reader038/viewer/2022100603/5592a4561a28ab6e798b45fe/html5/thumbnails/10.jpg)
結局
• GCのシステムにどのローカル変数が生きているポインタを持っているかを教える
– コンパイラが変数の型を把握していることを利用
![Page 11: Precise garbage collection for c](https://reader038.vdocuments.site/reader038/viewer/2022100603/5592a4561a28ab6e798b45fe/html5/thumbnails/11.jpg)
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](https://reader038.vdocuments.site/reader038/viewer/2022100603/5592a4561a28ab6e798b45fe/html5/thumbnails/12.jpg)
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](https://reader038.vdocuments.site/reader038/viewer/2022100603/5592a4561a28ab6e798b45fe/html5/thumbnails/13.jpg)
いろいろやってみた(PTL Scheme)
• PLT SchemeのGCをConservative GCからPrecise GCにしてみた
• 最初に説明した通り、メモリ使用量が激減
• 実行速度は– メモリアロケーションが多いベンチマークは20%くらい速くなる
– メモリアロケーションが少ないベンチマークは10~20 %遅くなる
![Page 14: Precise garbage collection for c](https://reader038.vdocuments.site/reader038/viewer/2022100603/5592a4561a28ab6e798b45fe/html5/thumbnails/14.jpg)
いろいろやってみた(Linuxカーネル!)
• カーネルなんて絶対メモリーリークしちゃいかんし、GCが欲しいよね
• なんかいろいろ面倒だったみたい。続きは論文で
• tmpfsからddコマンドでファイルアクセス– GC付きのものが4割ほど遅い
• HDDからddコマンドでファイルアクセス–あまり変わらない
![Page 15: Precise garbage collection for c](https://reader038.vdocuments.site/reader038/viewer/2022100603/5592a4561a28ab6e798b45fe/html5/thumbnails/15.jpg)
まとめ
• この技術すげー。今後、いろんなところで使われるようになるはず。
• GC本第2版は保守的GCの章を書き換えないといかんかもしれませんねー
• 8ccでサポート予定だから楽しみ http://github.com/rui314/8cc
![Page 16: Precise garbage collection for c](https://reader038.vdocuments.site/reader038/viewer/2022100603/5592a4561a28ab6e798b45fe/html5/thumbnails/16.jpg)
ご清聴
ありがとう
ございました