erg*_*ito 0 ruby garbage-collection module class anonymous-class
我想知道为什么以下代码显然不会垃圾收集那些应该不再引用的匿名模块(未扩展/包含,未命名,包含设置为nil的数组)。
如果有人能用相对简单/通用的编程语言来澄清幕后的状况,我将不胜感激。是否有一种特殊的红宝石方法可以实现这一目标?匿名模块/类不能被垃圾回收吗?还是我只是被我得到的内存统计数据误导了?
注意:我使用的是Ruby 1.9.3;不知道ruby 2.x是否会改变任何东西...注2:无论模块是否定义foo方法,结果都是相同的
提前致谢。
puts("INITIAL OBJECT SPACE OBJECTS : #{ObjectSpace.count_objects}")
i = 100000
ms = []
i.times do
    ms << Module.new do
        def foo()
             puts('foo method called')
        end
    end
end
puts("#{i} MODULES CREATED")
puts("OBJECT SPACE OBJECTS : #{ObjectSpace.count_objects}")
ms = nil
ObjectSpace.garbage_collect
puts("#{i} MODULES GARBAGE COLLECTED")
puts("WAITING TO END PROGRAM")
stop = gets
puts("FINAL OBJECT SPACE OBJECTS : #{ObjectSpace.count_objects}")
我说“显然不会进行垃圾回收”,因为我的OS任务管理器没有显示进程中内存使用的任何减少,并且调用ObjectSpace.count_objects会产生以下内容,我读错了(是吗?)为:没有内存您模块使用的模块尚未释放。
初始对象空间对象:{:TOTAL => 14730,:FREE => 251,:T_OBJECT => 8,:T_CLASS => 542,:T_MODULE => 21,:T_FLOAT => 7,:T_STRING => 6349,:T_REGEXP => 24,:T_ARRAY => 1009,:T_HASH => 14,:T_BIGNUM => 3,:T_FILE => 10,:T_DATA => 408,:T_MATCH => 108,:T_COMPLEX => 1,:T_NODE => 5956,:T_ICLASS => 19}
创建了100000个模块
对象空间对象:{:TOTAL => 311794,:FREE => 59829,:T_OBJECT => 6,:T_CLASS => 542,:T_MODULE => 100021,:T_FLOAT => 7,:T_STRING => 3332,:T_REGEXP = > 22,:T_ARRAY => 23868,:T_HASH => 10,:T_BIGNUM => 3,:T_FILE => 3,:T_DATA => 100324,:T_COMPLEX => 1,:T_NODE => 23807,:T_ICLASS => 19 }
已收集100000个模块垃圾,等待结束程序
最终对象空间对象:{:TOTAL => 311794,:FREE => 107155,:T_OBJECT => 6,:T_CLASS => 542,:T_MODULE => 100021,:T_FLOAT => 7,:T_STRING => 3335,:T_REGEXP => 22,:T_ARRAY => 203,:T_HASH => 10,:T_BIGNUM => 3,:T_FILE => 3,:T_DATA => 100324,:T_COMPLEX => 1,:T_NODE => 143,:T_ICLASS => 19}
调用GC.start或ObjectSpace.garbage_collect 并不意味着将执行垃圾回收。这只是Ruby运行时的提示。
在某些平台上,Ruby运行时甚至无法启动垃圾回收,因为垃圾回收器甚至都不是Ruby运行时的一部分,例如在JRuby或IronRuby上。
通常,Ruby运行时将自行决定何时执行垃圾回收。通常,那是内存不足的时候。100000个模块不是那么大,因此根本不需要执行GC周期。
而且,即使在GC周期之后,大多数Ruby实现也绝不会将内存释放回OS。
因此,ObjectSpace不收缩的事实并不一定意味着您存在内存泄漏。这可能只是意味着Ruby运行时尚未认为有必要运行GC周期。
另外请注意,如果您从IRB,撬,一个IDE控制台或其他一些不规范的环境中,这代码,那么很可能的情况是,那些对一些这些模块的保持。例如,Pry将最后100个命令的结果存储在历史记录数组中。(_out_[5]输入示例程序后,尝试在Pry中进行评估。)