带有圆形对象引用的Ruby中的Garbarge集合

时间:2022-08-23 00:23:34

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.

我在Ruby中遇到垃圾收集问题,我认为应该是垃圾收集的对象不是垃圾收集。

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:

做一些制作对象的东西,并找到相关的对象ID。 GC.start,然后:

> 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.

看起来这里有一个圆形参考模式,但它们都完全包含在这四个对象中,因此Mark-and-Sweep收集器应该找到并删除它们。

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?

因此,我的find_dependencies_function,Mass gem或Ruby的垃圾收集器中都存在错误。如何缩小此范围以找出问题所在并解决此内存泄漏问题?

1 个解决方案

#1


3  

The GC in Ruby works essentially like so:

Ruby中的GC基本上是这样的:

  1. Mark all global objects as live.

    将所有全局对象标记为活动。

  2. 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.

因此,在循环引用的情况下,A保持在A上的A将获得GC'd,因为它们都不被活动对象持有。

Per the comments, something is necessarily holding onto the object somewhere... Or maybe Mass is catching RangeError or something...

根据评论,某些内容必然会保留在某个对象上...或者Mass可能会捕获RangeError或其他东西......

>> 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

#1


3  

The GC in Ruby works essentially like so:

Ruby中的GC基本上是这样的:

  1. Mark all global objects as live.

    将所有全局对象标记为活动。

  2. 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.

因此,在循环引用的情况下,A保持在A上的A将获得GC'd,因为它们都不被活动对象持有。

Per the comments, something is necessarily holding onto the object somewhere... Or maybe Mass is catching RangeError or something...

根据评论,某些内容必然会保留在某个对象上...或者Mass可能会捕获RangeError或其他东西......

>> 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