Project

General

Profile

Bug #10431

Updated by nobu (Nobuyoshi Nakada) over 5 years ago

GC_ENABLE_LAZY_SWEEP=0と設定してrubyをビルドし,以下のコードを 
 実行した場合,GC時にオブジェクトが解放されていないように見えます. 

 ~~~ 
 $ ../configure    CFLAGS="-DGC_ENABLE_LAZY_SWEEP=0" && make miniruby 
 $ cat bug2.rb 
 GC.disable 
 10000.times { Object.new } 
 total_freed_objects1 = GC.stat[:total_freed_objects] 
 GC.enable 
 GC.start(full_mark: true, immediate_sweep: true) 
 total_freed_objects2 = GC.stat[:total_freed_objects] 
 puts "freed object : #{total_freed_objects2 - total_freed_objects1}" 

 $ ./miniruby -v 
 ruby 2.2.0dev (2014-10-26 trunk 48073) [x86_64-darwin14] 
 $ ./miniruby bug2.rb 
 freed object : 0 

 ~~~ 

 また,rubyのコンパイルフラグをGC_ENABLE_LAZY_SWEEP=0, 
 RGENGC_CHECK_MODE=1と設定した上でビルドし,以下のコードを実行すると 
 assertで落ちます. 

 ~~~ 
 $ ./miniruby -e '10000.times { Object.new }' 
 Assertion failed: (objspace->flags.stat == gc_stat_none), function gc_start, file ../gc.c, line 5802. 
 [1]      91336 abort        ./miniruby -e '10000.times { Object.new }' 
 ~~~ 

 sweepフェーズにてGC_ENABLE_LAZY_SWEEP!=1の時のみsweepが実行されるのが 
 原因のようですので,これを修正するパッチを作りました. 

 ~~~diff ~~~ 
 diff --git a/gc.c b/gc.c 
 index a27cc01..979e2e0 100644 
 --- a/gc.c 
 +++ b/gc.c 
 @@ -3314,9 +3314,8 @@ static void 
  gc_sweep_rest(rb_objspace_t *objspace) 
  { 
      rb_heap_t *heap = heap_eden; /* lazy sweep only for eden */ 
 - 
 -      if (is_lazy_sweeping(heap)) { 
 -         while (is_lazy_sweeping(heap)) { 
 +      if ((heap)->sweep_pages != NULL) { 
 +         while ((heap)->sweep_pages != NULL) { 
             gc_sweep_step(objspace, heap); 
         } 
      } 
 ~~~ 

 English: 

 When I tried to compile ruby with GC_ENABLE_LAZY_SWEEP=0, 
 Ruby does not sweep objects immediatly. 

 ~~~ 
 $ ../configure    CFLAGS="-DGC_ENABLE_LAZY_SWEEP=0" && make miniruby 
 $ cat bug2.rb 
 GC.disable 
 10000.times { Object.new } 
 total_freed_objects1 = GC.stat[:total_freed_objects] 
 GC.enable 
 GC.start(full_mark: true, immediate_sweep: true) 
 total_freed_objects2 = GC.stat[:total_freed_objects] 
 puts "freed object : #{total_freed_objects2 - total_freed_objects1}" 

 $ ./miniruby -v 
 ruby 2.2.0dev (2014-10-26 trunk 48073) [x86_64-darwin14] 
 $ ./miniruby bug2.rb 
 freed object : 0 
 ~~~ 

 In addition, when I set GC_ENABLE_LAZY_SWEEP=0 and RGENGC_CHECK_MODE=1 
 ruby gives me assertion error like this: 

 ~~~ 
 $ ./miniruby -e '10000.times { Object.new }' 
 Assertion failed: (objspace->flags.stat == gc_stat_none), function gc_start, file ../gc.c, line 5802. 
 [1]      91336 abort        ./miniruby -e '10000.times { Object.new }' 
 ~~~ 

 The following patch fix this problem. 

 ~~~diff ~~~ 
 diff --git a/gc.c b/gc.c 
 index a27cc01..979e2e0 100644 
 --- a/gc.c 
 +++ b/gc.c 
 @@ -3314,9 +3314,8 @@ static void 
  gc_sweep_rest(rb_objspace_t *objspace) 
  { 
      rb_heap_t *heap = heap_eden; /* lazy sweep only for eden */ 
 - 
 -      if (is_lazy_sweeping(heap)) { 
 -         while (is_lazy_sweeping(heap)) { 
 +      if ((heap)->sweep_pages != NULL) { 
 +         while ((heap)->sweep_pages != NULL) { 
             gc_sweep_step(objspace, heap); 
         } 
      } 

 ~~~

Back