From: Eric Hodel Date: 2008-08-01T16:08:57+09:00 Subject: Re: gc doesn't collect? On Jul 31, 2008, at 22:18 PM, Roger Pack wrote: > Just to clear up confusion: > I believe that > > GC.start 'forces' a garbage collection Well, if there's no garbage then there's no collection. > , and that > do...end and > {...} scopes do indeed have their own scope and local variables, as > methods do. Ruby scope, yes, but that doesn't mean the C stack has no pointers to your object. There's no guarantee that all references your object have been clobbered by subsequent calls. (Or that there are values on the C stack that look like pointers to your objects.) > interestingly, > > def go > 1.times { a = 'a'*1000}; > end > go > 30.times { GC.start }; > print ObjectSpace.each_object{|o| print o} > > yields the same errant results. I might look into it sometime. Very > weird. This is simply how ruby's conservative collector works. > Now for some questions: > > currently the GC marks live objects then sweeps to find any free > objects--except it doesn't actually free any objects that are free but > need finalization. I think you found a bug. Ruby 1.6 called finalizers after sweep, but 1.8.6 doesn't. $ cat final.rb $finalizer_proc = proc do |obj_id| puts "#{obj_id} finalized" end def a() b end def b() c end def c() d end def d() e end def e() f end def f() g end def g() h end def h() i end def i() j end def j() k end def k() make_obj end def make_obj o = Object.new ObjectSpace.define_finalizer o, $finalizer_proc o.__id__ end obj_id = a puts "#{obj_id} created" a = [] s = 'a' begin loop do ObjectSpace._id2ref obj_id a << s.succ! print "#{s}\r" end rescue RangeError puts puts "#{obj_id} collected" end $ ruby -v final.rb ruby 1.8.6 (2008-03-03 patchlevel 114) [universal-darwin9.0] 81660 created avr 81660 collected 81660 finalized $ ruby16 -v final.rb ruby 1.6.8 (2005-09-21) [i386-darwin9.4.0] 1117686 created 1117686 finalized omu 1117686 collected $ > It seems to only do finalizations when a user > explicitly calls GC.start, or when the program terminates. Is there a > reason for this 'deferred_final_list' activity? This patch seems to restore 1.6 behavior: $ svn diff gc.c Index: gc.c =================================================================== --- gc.c (revision 18230) +++ gc.c (working copy) @@ -1196,7 +1196,7 @@ gc_sweep() /* clear finalization list */ if (final_list) { - deferred_final_list = final_list; + finalize_list(final_list); return; } free_unused_heaps(); $ ./miniruby -I./lib -I.ext/common -I./- -r./ext/purelib.rb ./ runruby.rb --extout=.ext -- ~/final.rb 605300 created 605300 finalized rek 605300 collected I'm not sure if it was accidentally removed or not, the log for r7090 points to several segmentation faults due to evil things done with finalizers and threads: http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-dev/24536 > Also is it true that objects marked FL_SINGLETON should never be > freed, > even if they are no longer referenced by any live code? Or is > FL_SINGLETON just used as an internal GC marker to mean 'the heap this > object comes from is entirely free--don't bother adding it to the > freelist since it is on the chopping block to be free'ed' and nothing > else? I'm not sure about this. It was added in the same changeset as above. I'll make a pointer to this thread on ruby-core.