![]() |
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. |
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. > |
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 |
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 ... |
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 02:23 AM. |
Powered by vBulletin®. Copyright ©2000 - 2013, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.