I'm having an issue with garbage collection in Ruby where an object that I think should be garbage collection is not being garbage collected.
require 'ruby-mass'
def find_dependencies(_object_id,_mapped = {})
mapped = _mapped
points_to_object = Mass.references(Mass[_object_id])
ids = points_to_object.keys.map{|x| /\#(\d*)/.match(x).captures.first.to_i}
mapped[_object_id] = ids
unmapped = ids - mapped.keys
unmapped.each do |x|
new_deps = find_dependencies(x,mapped)
mapped.merge(new_deps)
end
mapped
end
Do some stuff that makes the objects, and find the relevant object ID. GC.start
, then:
> find_dependencies(144789180)
=> {144789180=>[61895480, 144786340, 147807540],
61895480=>[144789180],
144786340=>[144789180],
147807540=>[144789180]}
It looks like there is a circular reference pattern here, but it is all completely contained in these four objects, so the Mark-and-Sweep collector should find them and remove them.
So, either there is a bug in my find_dependencies_function, the Mass gem, or Ruby's garbage collector. How do I narrow this down to find out what the problem is and solve this memory leak?
yes Java Garbage collector handles circular-reference! How? There are special objects called called garbage-collection roots (GC roots). These are always reachable and so is any object that has them at its own root.
To handle the problem of circular references in C#, you should use garbage collection. It detects and collects circular references. The garbage collector begins with local and static and it marks each object that can be reached through their children. Through this, you can handle the issues with circular references.
The Ruby Garbage Collector module is an interface to Ruby's mark and sweep garbage collection mechanism. While it runs automatically in the background when needed, the GC module lets you call the GC manually whenever required and gain insights into how garbage collection cycles are running.
Chains of reference objects. A given path to an object can contain more than one kind of reference object, which creates a chain of reference objects. The garbage collector processes reference objects in order from strongest to weakest.
The GC in Ruby works essentially like so:
Mark all global objects as live.
Sweep through objects, garbage collect unless a parent is live.
So, in the case of a circular reference, A holding onto B holding onto A would get GC'd because neither is being held by a live object.
Per the comments, something is necessarily holding onto the object somewhere... Or maybe Mass is catching RangeError or something...
>> a = {}
=> {}
>> a[:a] = a
=> {:a=>{...}}
>> a.object_id
=> 2269556540
>> a = nil
=> nil
>> GC.start
=> nil
>> ObjectSpace._id2ref(2269556540)
RangeError: 0x8746af3c is recycled object
from (irb):17:in `_id2ref'
from (irb):17
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With