查看: 2543|回复: 6

[已经解决] 请问Ruby的GC的原理?

[复制链接]

…あたしは天

梦石
0
星屑
2308
在线时间
4033 小时
注册时间
2010-10-4
回帖
10548

开拓者贵宾

发表于 2014-5-1 15:38:33 | 显示全部楼层 |阅读模式

加入我们,或者,欢迎回来。

您需要 登录 才可以下载或查看,没有账号?注册会员

×

现在有点搞不懂一个对象什么时候会被回收了,于是写了一点代码。下面是Ruby2.0.0中的运行结果

[pre lang="ruby" line="1"]
def test
  GC.start
  arr = []
  100000.times { a_method(arr) }
  p arr.size
end

# test1
def a_method(arr)
  obj = 'temp'
  ObjectSpace.define_finalizer(obj, proc {|id| arr.push(id) })
end
test #=> 0

# test2
def a_method(arr)
  ObjectSpace.define_finalizer('temp', proc {|id| arr.push(id) })
end
test #=> 69872
[/pre]

在test1中,虽然‘temp’字符串被赋给了变量obj,但是很快obj就出了作用域无法引用了。这个字符串应该是可以被回收的,可是最后却没有被回收。
在test2中,直接把'temp'作为参数传给了define_finalizer,这样倒是可以触发ruby的垃圾回收机制。

所以到底怎么样的对象可以触发ruby的垃圾回收?我以前一直觉得,当一个对象不被任何东西引用的时候就可以被回收了。但是test1证明似乎不是这样?求科普~~

点评

http://ruby-doc.org/core-2.0.0  发表于 2014-5-1 21:23
梦石
0
星屑
266
在线时间
2355 小时
注册时间
2009-3-13
回帖
2257

贵宾

发表于 2014-5-1 18:52:31 | 显示全部楼层
本帖最后由 Sion 于 2014-5-1 19:01 编辑

貌似那个 define_finalizer 导致无法回收。
[pre lang="ruby" line="1"]class T
end

def m1
  p a = T.new
end

m1
GC.start
ObjectSpace.each_object( T ) {|obj| p obj}
puts '已释放 m1中的 T.new'

def m2
  p a = T.new
  ObjectSpace.define_finalizer( a, proc {} )
end

m2
GC.start
ObjectSpace.each_object( T ) {|obj| p obj}
puts '无法释放 m2 中的 T.new'[/pre]
运行环境是 1.9.2
这就是 Ruby 饱受诟病的内存泄露吧。其实都是些鸡肋功能...

点评

要看源码吧,这种事还是留给 ruby 开发人员做算咯,用户想点办法绕开它就行了。  发表于 2014-5-1 20:12
这样啊,那顶楼的test2为什么可以回收呢?  发表于 2014-5-1 19:46

评分

参与人数 1星屑 +20 收起 理由
taroxd + 20 认可答案

查看全部评分

回复

使用道具 举报

梦石
0
星屑
50
在线时间
3 小时
注册时间
2014-5-9
回帖
5
发表于 2014-5-13 22:32:35 | 显示全部楼层
本帖最后由 masix8 于 2014-5-13 22:34 编辑

应该是这样的,定义obj=‘temp’的时候给了一个内存段来存数据,而后面还有使用,这一段是不会当作垃圾的

那个代码里面m2也是,之前定义,后面使用的局部变量不会当作垃圾,全局变量无论何时都不会当作垃圾
回复

使用道具 举报

头像被屏蔽
梦石
0
星屑
653
在线时间
3774 小时
注册时间
2011-2-26
回帖
1577

开拓者

发表于 2014-5-14 00:35:07 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
签名被屏蔽
回复

使用道具 举报

精灵族の天使<

梦石
0
星屑
1712
在线时间
3039 小时
注册时间
2007-3-16
回帖
33092

开拓者贵宾

发表于 2014-5-14 08:05:32 | 显示全部楼层
GC只会回收已经不会再引用的东西【也就是断开连接】的东西。
最著名的例子就是
  1. RPG::Cache.clear

  2. Module RPG
  3. Module Cache
  4.   def self.clear
  5. @Cache= {} #清理所有@cache的所有链接
  6.    GC.start #由于失去链接,所有的内存都会被清理
  7.   end
  8. end
  9. end
复制代码

点评

引用次数到零的时候灭掉~  发表于 2014-5-15 06:16
求引用计数的方法。【是不是如果引用的次数达到一定限制就会自动的标记为outdated而强制清除?】  发表于 2014-5-14 21:28
这个基本方法就叫做标记扫除。。还有一种方法叫引用计数。。常见的高级GC策略都是这两个组合来的  发表于 2014-5-14 21:15
我本来就是这么理解的  发表于 2014-5-14 18:40
回复

使用道具 举报

头像被屏蔽
梦石
0
星屑
653
在线时间
3774 小时
注册时间
2011-2-26
回帖
1577

开拓者

发表于 2014-5-14 21:09:58 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
签名被屏蔽
回复

使用道具 举报

头像被屏蔽
梦石
0
星屑
653
在线时间
3774 小时
注册时间
2011-2-26
回帖
1577

开拓者

发表于 2014-5-14 23:10:36 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
签名被屏蔽
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

Powered by Discuz! X5.0 © 2001-2026 Discuz! Team.

在本版发帖返回顶部