From: Robert Klemme Date: 2008-09-17T23:24:54+09:00 Subject: Re: Threads preventing garbage collection? 2008/9/17 Brian Candler : > Robert Klemme wrote: >>> For some reason, in the following code the instances of object Foo are >>> prevented from being garbage collected. >> >> No, they are not collected. This is something different! > > OK, please consider my question rephrased as "why are these objects not > collected?" > > Let me increase the number of objects: > > def make_thread > Thread.new { sleep 10000 } > end > > class Foo > attr_accessor :bar > end > > 10000.times { |i| > f = Foo.new > f.bar = make_thread > } > > GC.start > sleep 1 > GC.start > > count = 0 > ObjectSpace.each_object(Foo) { |o| count += 1 } > puts "#{count} objects" > > On my machine, this program uses about 150MB of RAM, and all 10,000 > objects are remaining at the end of the run. > > Have I done something here which is "wrong"? Are the known pitfalls of > the garbage collector documented anywhere, or ways to write programs so > as to avoid them? You probably just did not allocate enough new objects to make the GC collect stuff. AFAIK there is also a minimal process size under which no GC occurs. > Or can it simply not be relied upon, ever? Yes, it can. Try this def make_thread Thread.new { sleep 2 } end class Module def count c = 0 ObjectSpace.each_object(self) { c += 1 } c end end Foo = Struct.new :bar 1000.times { Foo.new.bar = make_thread } # use memory Thread.new { loop { Array.new(1_000_000); sleep 0.1 } } loop do puts Foo.count GC.start sleep 1 end Cheers robert -- use.inject do |as, often| as.you_can - without end