Hello. >Because ruby's GC is conservative. I found interesting phenomenon. def format(num) num.to_s.gsub(/(\d{1,3})(?=\d{3}+$)/) { $1 + "," } end def count(type) count = 0 capacity = 0 ObjectSpace.each_object(type) do |o| count += 1 capacity += o.capacity end puts "#{type}" puts " count = #{format(count)}" puts " capacity = #{format(capacity)}" end def pause GC.enable GC.start GC.disable count(String) count(Array) puts sleep 5 end class A def run arr = [] 800000.times { arr << "d" * 7 } pause end end GC.disable A.new.run 1.times { pause } # not freed pause # but freed here //////////////////////////////////////////////////////// I have dived into gc.c, and applied this patch. Index: gc.c =================================================================== RCS file: /src/ruby/gc.c,v retrieving revision 1.168.2.37 diff -u -w -b -p -r1.168.2.37 gc.c --- gc.c 13 Feb 2006 09:10:53 -0000 1.168.2.37 +++ gc.c 28 Feb 2006 07:04:44 -0000 @@ -1354,6 +1354,7 @@ garbage_collect() setjmp(save_regs_gc_mark); mark_locations_array((VALUE*)save_regs_gc_mark, sizeof(save_regs_gc_mark) / sizeof(VALUE *)); #if STACK_GROW_DIRECTION < 0 + printf("----------> %p %p\n", STACK_END, rb_gc_stack_start); rb_gc_mark_locations((VALUE*)STACK_END, rb_gc_stack_start); #elif STACK_GROW_DIRECTION > 0 rb_gc_mark_locations(rb_gc_stack_start, (VALUE*)STACK_END + 1); //////////////////////////////////////////// E:\ruby-cvs\win32_1_8>miniruby \a.rb ----------> 0012FD0C 0012FFFC ----------> 0012E4C0 0012FFFC String count = 800,111 capacity = 5,602,208 Array count = 7 capacity = 806,581 ----------> 0012DD10 0012FFFC String count = 800,116 capacity = 5,602,275 Array count = 7 capacity = 806,581 ----------> 0012ED48 0012FFFC String count = 113 capacity = 2,219 Array count = 6 capacity = 96 //////////////////////////////////////////// STACK_END is more far from rb_gc_stack_start on 1.times { pause } (same thing happens on loop { pause }) this means ruby uses more stack on block execution. Because rb_gc_mark_locations marks all objects in the range of STACK_END to rb_gc_stack_start. if GC.start runs inside block, block needs more stack, so more objects can be wrongly marked as alive. (As you can see, last `pause` is outside of block, so less stack is used, huge array goes out of stack range, it is freed) # But I was suprised of this result. I heard conservative GC can mark dead object wrongly # but this was a little differenct from what I expected. Maybe I'm missing something...