Ruby GC実装の歴史/Ruby1.9.3のGCを読む
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
]
開始行:
[[Ruby GC実装の歴史を読む]]
#contents
*はじめに [#e06d45da]
Ruby 1.9.3にて、lazy sweepという仕組みが導入されました。1...
*lazy sweepの前に [#i2a3f444]
lazy sweepを見ていく前にRHGで取り上げられている1.7.3から1...
**heaps_slot構造体 [#pc7389e1]
1.7.3ではheapsはRVALUEのポインタのポインタでしたが、1.8(...
**rb_objspace構造体 [#w644e6a0]
1.9.1から導入されheapsなどの実体はこの構造体に入るように...
従来グローバル変数だったheapsなどは
#code(C){{
#define heaps objspace->heap.ptr
#define heaps_length objspace->heap.length
#define heaps_used objspace->heap.used
#define freelist objspace->heap.freelist
}}
のようにdefineされており、変更なくアクセスできるようにな...
*rb_newobj() [#se44e8d5]
では、rb_newobj()から見ていきましょう。rb_newobj()を上か...
#code(C){{
if (UNLIKELY(!freelist)) {
if (!gc_lazy_sweep(objspace)) {
during_gc = 0;
rb_memerror();
}
}
}}
いきなりlazy sweepに出くわしてしまいました(笑)
ちなみに1.9.2では相当部分は以下のようになっています。
#code(C){{
if ((ruby_gc_stress && !ruby_disable_gc_stress) || !f...
if (!heaps_increment(objspace) && !garbage_collec...
during_gc = 0;
rb_memerror();
}
}
}}
使われてないRVALUEがなかった場合、heaps伸ばす必要があった...
*gc_lazy_sweep() [#k68c31a9]
というわけでgc_lazy_sweep()を見てみましょう。プロファイル...
#code(C){{
static int
gc_lazy_sweep(rb_objspace_t *objspace)
{
int res;
if (!ready_to_gc(objspace)) return TRUE;
during_gc++;
if (objspace->heap.sweep_slots) {
res = lazy_sweep(objspace);
if (res) {
return res;
}
after_gc_sweep(objspace);
}
else {
if (heaps_increment(objspace)) {
during_gc = 0;
return TRUE;
}
}
gc_marks(objspace);
before_gc_sweep(objspace);
if (objspace->heap.free_min > (heaps_used * HEAP_OBJ_...
set_heaps_increment(objspace);
}
if(!(res = lazy_sweep(objspace))) {
after_gc_sweep(objspace);
if(freelist) {
res = TRUE;
during_gc = 0;
}
}
return res;
}
}}
処理は大きく2つに分かれています。
+sweep_slotsがあったらlazy_sweep()を呼び出してオブジェク...
+どちらも駄目ならオブジェクトのマークを行い、before_gc_sw...
ポイントはsweep_slotsのようです。lazy_sweep()はsweep_slot...
*gc_marks() [#s8e4764f]
gc_marks()読むとマークのやり方がちょっと変わったことに気...
1.9.2までは、
-ルートオブジェクトを起点にマシンスタックが尽きるまでマーク
-マークしきれない分はmark_stackに積んでおいて後でマーク
ですが、1.9.3からは
+ルートオブジェクトをmark_stackに積む(それぞれのマーク関...
+gc_mark_stacked_objects()を呼び出して子要素をマークする...
+gc_mark_children()では子要素をマークするためにgc_mark()...
といった感じになっています。1.9.2まではmark_stackが有限サ...
ちなみにgc_mark_children()では可能な限り再帰呼び出しを減...
さてというわけでgc_marks()を見てきました。・・・mark_stac...
*before_gc_sweep() [#b7f0b6e8]
#code(C){{
static void
before_gc_sweep(rb_objspace_t *objspace)
{
freelist = 0;
objspace->heap.do_heap_free = (size_t)((heaps_used * ...
objspace->heap.free_min = (size_t)((heaps_used * HEAP...
if (objspace->heap.free_min < initial_free_min) {
objspace->heap.do_heap_free = heaps_used * HEAP_O...
objspace->heap.free_min = initial_free_min;
}
objspace->heap.sweep_slots = heaps;
objspace->heap.free_num = 0;
/* sweep unlinked method entries */
if (GET_VM()->unlinked_method_entry_list) {
rb_sweep_method_entry(GET_VM());
}
}
}}
おや、ありました。結局、スイープ対象のスロットってわけで...
*lazy_sweep() [#u3522a99]
では次にlazy_sweep()。
#code(C){{
static int
lazy_sweep(rb_objspace_t *objspace)
{
struct heaps_slot *next;
heaps_increment(objspace);
while (objspace->heap.sweep_slots) {
next = objspace->heap.sweep_slots->next;
slot_sweep(objspace, objspace->heap.sweep_slots);
objspace->heap.sweep_slots = next;
if (freelist) {
during_gc = 0;
return TRUE;
}
}
return FALSE;
}
}}
slot_sweep()呼んで空きオブジェクトができたらそこで止めて...
*おわりに [#x1e65dd4]
というわけでコードを見てきましたがlazy sweepの動きをまと...
+まずマークする
+1スロットについてマークされてないオブジェクトを解放して...
といった感じです。さてそうすると、「マークされた後、使わ...
終了行:
[[Ruby GC実装の歴史を読む]]
#contents
*はじめに [#e06d45da]
Ruby 1.9.3にて、lazy sweepという仕組みが導入されました。1...
*lazy sweepの前に [#i2a3f444]
lazy sweepを見ていく前にRHGで取り上げられている1.7.3から1...
**heaps_slot構造体 [#pc7389e1]
1.7.3ではheapsはRVALUEのポインタのポインタでしたが、1.8(...
**rb_objspace構造体 [#w644e6a0]
1.9.1から導入されheapsなどの実体はこの構造体に入るように...
従来グローバル変数だったheapsなどは
#code(C){{
#define heaps objspace->heap.ptr
#define heaps_length objspace->heap.length
#define heaps_used objspace->heap.used
#define freelist objspace->heap.freelist
}}
のようにdefineされており、変更なくアクセスできるようにな...
*rb_newobj() [#se44e8d5]
では、rb_newobj()から見ていきましょう。rb_newobj()を上か...
#code(C){{
if (UNLIKELY(!freelist)) {
if (!gc_lazy_sweep(objspace)) {
during_gc = 0;
rb_memerror();
}
}
}}
いきなりlazy sweepに出くわしてしまいました(笑)
ちなみに1.9.2では相当部分は以下のようになっています。
#code(C){{
if ((ruby_gc_stress && !ruby_disable_gc_stress) || !f...
if (!heaps_increment(objspace) && !garbage_collec...
during_gc = 0;
rb_memerror();
}
}
}}
使われてないRVALUEがなかった場合、heaps伸ばす必要があった...
*gc_lazy_sweep() [#k68c31a9]
というわけでgc_lazy_sweep()を見てみましょう。プロファイル...
#code(C){{
static int
gc_lazy_sweep(rb_objspace_t *objspace)
{
int res;
if (!ready_to_gc(objspace)) return TRUE;
during_gc++;
if (objspace->heap.sweep_slots) {
res = lazy_sweep(objspace);
if (res) {
return res;
}
after_gc_sweep(objspace);
}
else {
if (heaps_increment(objspace)) {
during_gc = 0;
return TRUE;
}
}
gc_marks(objspace);
before_gc_sweep(objspace);
if (objspace->heap.free_min > (heaps_used * HEAP_OBJ_...
set_heaps_increment(objspace);
}
if(!(res = lazy_sweep(objspace))) {
after_gc_sweep(objspace);
if(freelist) {
res = TRUE;
during_gc = 0;
}
}
return res;
}
}}
処理は大きく2つに分かれています。
+sweep_slotsがあったらlazy_sweep()を呼び出してオブジェク...
+どちらも駄目ならオブジェクトのマークを行い、before_gc_sw...
ポイントはsweep_slotsのようです。lazy_sweep()はsweep_slot...
*gc_marks() [#s8e4764f]
gc_marks()読むとマークのやり方がちょっと変わったことに気...
1.9.2までは、
-ルートオブジェクトを起点にマシンスタックが尽きるまでマーク
-マークしきれない分はmark_stackに積んでおいて後でマーク
ですが、1.9.3からは
+ルートオブジェクトをmark_stackに積む(それぞれのマーク関...
+gc_mark_stacked_objects()を呼び出して子要素をマークする...
+gc_mark_children()では子要素をマークするためにgc_mark()...
といった感じになっています。1.9.2まではmark_stackが有限サ...
ちなみにgc_mark_children()では可能な限り再帰呼び出しを減...
さてというわけでgc_marks()を見てきました。・・・mark_stac...
*before_gc_sweep() [#b7f0b6e8]
#code(C){{
static void
before_gc_sweep(rb_objspace_t *objspace)
{
freelist = 0;
objspace->heap.do_heap_free = (size_t)((heaps_used * ...
objspace->heap.free_min = (size_t)((heaps_used * HEAP...
if (objspace->heap.free_min < initial_free_min) {
objspace->heap.do_heap_free = heaps_used * HEAP_O...
objspace->heap.free_min = initial_free_min;
}
objspace->heap.sweep_slots = heaps;
objspace->heap.free_num = 0;
/* sweep unlinked method entries */
if (GET_VM()->unlinked_method_entry_list) {
rb_sweep_method_entry(GET_VM());
}
}
}}
おや、ありました。結局、スイープ対象のスロットってわけで...
*lazy_sweep() [#u3522a99]
では次にlazy_sweep()。
#code(C){{
static int
lazy_sweep(rb_objspace_t *objspace)
{
struct heaps_slot *next;
heaps_increment(objspace);
while (objspace->heap.sweep_slots) {
next = objspace->heap.sweep_slots->next;
slot_sweep(objspace, objspace->heap.sweep_slots);
objspace->heap.sweep_slots = next;
if (freelist) {
during_gc = 0;
return TRUE;
}
}
return FALSE;
}
}}
slot_sweep()呼んで空きオブジェクトができたらそこで止めて...
*おわりに [#x1e65dd4]
というわけでコードを見てきましたがlazy sweepの動きをまと...
+まずマークする
+1スロットについてマークされてないオブジェクトを解放して...
といった感じです。さてそうすると、「マークされた後、使わ...
ページ名: