2008/9/17 Brian Candler <b.candler / pobox.com>:
> 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