Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   Ruby (http://www.velocityreviews.com/forums/f66-ruby.html)
-   -   Circular References: How to prove that they are garbage collected (http://www.velocityreviews.com/forums/t816309-circular-references-how-to-prove-that-they-are-garbage-collected.html)

Karsten Meier 08-23-2004 09:20 PM

Circular References: How to prove that they are garbage collected
 
Hello Ruby Fans

I'm converting a perl example which deals with the circular data
structures, and how to make sure they are destroyed properly.
(For the pleac cookbook, pleac.sourceforge.net)

I have read several times that the garbage collector has no problems
with circular references, so I tried to prove it.
But with my ruby 1.8.0 it looks like the garbage collector
does not destroys the Node A, B and C, but only the lonely node:

GC.enable

class RingNode
attr_accessor :next
attr_accessor :prev
attr_reader :name

def initialize(aName)
@name = aName
ObjectSpace.define_finalizer(self,
self.class.method(:finalize).to_proc)
end

def RingNode.finalize(id)
puts "Node #{id} dying"
end

def RingNode.show_all_objects
ObjectSpace.each_object {|id|
puts id.name if id.class == RingNode
}
end
end

a = RingNode.new("Node A")
b = RingNode.new("Node B")
c = RingNode.new("Node C")
a.next = b
b.next = c
c.next = a
a.prev = c
c.prev = b
b.prev = a
lonely = RingNode.new("Lonely node")

a = nil
b = nil
c = nil
lonely = nil

GC.start
puts "Garbage Collection called"
RingNode.show_all_objects
puts "End of Program"


What happens is that Noda A,B,C get destroyed, but after the end of the
program. If I comment out the finalizer (in case I made an error with
it) and only use the ObjectSpace.each_object, I see also Node A,B,C
after the garbage collection.


Joel VanderWerf 08-23-2004 09:43 PM

Re: Circular References: How to prove that they are garbage collected
 
Karsten Meier wrote:
> Hello Ruby Fans
>
> I'm converting a perl example which deals with the circular data
> structures, and how to make sure they are destroyed properly.
> (For the pleac cookbook, pleac.sourceforge.net)
>
> I have read several times that the garbage collector has no problems
> with circular references, so I tried to prove it.
> But with my ruby 1.8.0 it looks like the garbage collector
> does not destroys the Node A, B and C, but only the lonely node:


"Only the lonely
Node the way I feel tonight"

... hehe. Sorry Roy Orbison.

Anyway, try it with the following 3 additional lines. All four nodes
print their message before the "Garbage colection called" message. I
think what's going on is conservatism. Keeping the local vars in a
method makes sure that stack frame is gone begore the GC starts.

> GC.enable
>
> class RingNode
> attr_accessor :next
> attr_accessor :prev
> attr_reader :name
>
> def initialize(aName)
> @name = aName
> ObjectSpace.define_finalizer(self,
> self.class.method(:finalize).to_proc)
> end
>
> def RingNode.finalize(id)
> puts "Node #{id} dying"
> end
>
> def RingNode.show_all_objects
> ObjectSpace.each_object {|id|
> puts id.name if id.class == RingNode
> }
> end
> end
>

def main
> a = RingNode.new("Node A")
> b = RingNode.new("Node B")
> c = RingNode.new("Node C")
> a.next = b
> b.next = c
> c.next = a
> a.prev = c
> c.prev = b
> b.prev = a
> lonely = RingNode.new("Lonely node")

end
>
> a = nil
> b = nil
> c = nil
> lonely = nil
>

main
> GC.start
> puts "Garbage Collection called"
> RingNode.show_all_objects
> puts "End of Program"
>
>
> What happens is that Noda A,B,C get destroyed, but after the end of the
> program. If I comment out the finalizer (in case I made an error with
> it) and only use the ObjectSpace.each_object, I see also Node A,B,C
> after the garbage collection.
>





Florian Gross 08-23-2004 09:45 PM

Re: Circular References: How to prove that they are garbage collected
 
Moin!

The problems is with the finalizer. It holds a reference to the object
AFAIK.

Maybe you could just capture the .object_id and use ObjectSpace._id2ref
to check whether the Objects still exist after you ran the GC?

Oh, or you could use a WeakRef.

Regards,
Florian Gross

Joel VanderWerf 08-23-2004 09:47 PM

Re: Circular References: How to prove that they are garbage collected
 

Oops... I put the end in the wrong place. It should be like this:

def main
a = RingNode.new("Node A")
b = RingNode.new("Node B")
c = RingNode.new("Node C")
a.next = b
b.next = c
c.next = a
a.prev = c
c.prev = b
b.prev = a
lonely = RingNode.new("Lonely node")

a = nil
b = nil
c = nil
lonely = nil
end

main
GC.start
...



Karsten Meier 08-23-2004 10:06 PM

Re: Circular References: How to prove that they are garbage collected
 
Thanks, this is doing the trick.
Even when I put the assignments to nil also in the function
(just to be sure that there is has nothing to do with C++ style
destruction of objects on the stack when leaving the function)


Joel VanderWerf wrote:
> Karsten Meier wrote:
>
>> Hello Ruby Fans
>>
>> I'm converting a perl example which deals with the circular data
>> structures, and how to make sure they are destroyed properly.
>> (For the pleac cookbook, pleac.sourceforge.net)
>>
>> I have read several times that the garbage collector has no problems
>> with circular references, so I tried to prove it.
>> But with my ruby 1.8.0 it looks like the garbage collector
>> does not destroys the Node A, B and C, but only the lonely node:

>
>
> "Only the lonely
> Node the way I feel tonight"
>
> ... hehe. Sorry Roy Orbison.
>
> Anyway, try it with the following 3 additional lines. All four nodes
> print their message before the "Garbage colection called" message. I
> think what's going on is conservatism. Keeping the local vars in a
> method makes sure that stack frame is gone begore the GC starts.
>
>> GC.enable
>>
>> class RingNode
>> attr_accessor :next
>> attr_accessor :prev
>> attr_reader :name
>>
>> def initialize(aName)
>> @name = aName
>> ObjectSpace.define_finalizer(self,
>> self.class.method(:finalize).to_proc)
>> end
>>
>> def RingNode.finalize(id)
>> puts "Node #{id} dying"
>> end
>>
>> def RingNode.show_all_objects
>> ObjectSpace.each_object {|id|
>> puts id.name if id.class == RingNode
>> }
>> end
>> end
>>

> def main
>
>> a = RingNode.new("Node A")
>> b = RingNode.new("Node B")
>> c = RingNode.new("Node C")
>> a.next = b
>> b.next = c
>> c.next = a
>> a.prev = c
>> c.prev = b
>> b.prev = a
>> lonely = RingNode.new("Lonely node")

>
> end
>
>>
>> a = nil
>> b = nil
>> c = nil
>> lonely = nil
>>

> main
>
>> GC.start
>> puts "Garbage Collection called"
>> RingNode.show_all_objects
>> puts "End of Program"
>>
>>
>> What happens is that Noda A,B,C get destroyed, but after the end of
>> the program. If I comment out the finalizer (in case I made an error
>> with it) and only use the ObjectSpace.each_object, I see also Node
>> A,B,C after the garbage collection.
>>

>
>
>



All times are GMT. The time now is 01:55 PM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.