aar*_*njg 11 ruby garbage-collection
我在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
Run Code Online (Sandbox Code Playgroud)
做一些制作对象的东西,并找到相关的对象ID.GC.start, 然后:
> find_dependencies(144789180)
=> {144789180=>[61895480, 144786340, 147807540],
61895480=>[144789180],
144786340=>[144789180],
147807540=>[144789180]}
Run Code Online (Sandbox Code Playgroud)
看起来这里有一个圆形参考图案,但它们都完全包含在这四个对象中,因此Mark-and-Sweep收集器应该找到并删除它们.
所以,我的find_dependencies_function,Mass gem或Ruby的垃圾收集器都有一个bug.如何缩小范围以找出问题所在并解决此内存泄漏问题?
Ruby 中的 GC 基本上是这样工作的:
将所有全局对象标记为活动对象。
扫描对象,垃圾收集,除非父对象还活着。
因此,在循环引用的情况下,A 持有 B 持有 A 会被 GC,因为两者都没有被活动对象持有。
根据评论,某些东西必然会在某个地方保留该对象......或者 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
Run Code Online (Sandbox Code Playgroud)