Ruby Symbol#to_proc泄漏1.9.2-p180中的引用? [英] Ruby Symbol#to_proc leaks references in 1.9.2-p180?

查看:90
本文介绍了Ruby Symbol#to_proc泄漏1.9.2-p180中的引用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好的,这是我第二次尝试调试我的Sinatra应用程序的内存问题.我相信这次我已将其固定在简单的示例代码中.

Ok, this is my second attempt at debugging the memory issues with my Sinatra app. I believe I have it nailed down into simple sample code this time.

似乎当我通过.map(&:some_method)过滤数组时,它会导致该数组中的项目无法得到垃圾回收.运行等效的.map{|x| x.some_method}完全可以.

It seems when I filter an array through .map(&:some_method), it causes the items in that array to not get garbage collected. Running the equivalent .map{|x| x.some_method} is totally fine.

演示:给出一个简单的示例类:

Demonstration: Given a simple sample class:

class C
  def foo
    "foo"
  end
end

如果我在IRB中运行以下命令,它将被正常收集:

If I run the following in IRB, it gets collected normally:

ruby-1.9.2-p180 :001 > a = 10.times.map{C.new}
 => [...]
ruby-1.9.2-p180 :002 > b = a.map{|x| x.foo}
 => ["foo", "foo", "foo", "foo", "foo", "foo", "foo", "foo", "foo", "foo"]
ruby-1.9.2-p180 :003 > ObjectSpace.each_object(C){}
 => 10
ruby-1.9.2-p180 :004 > a = nil
 => nil
ruby-1.9.2-p180 :005 > b = nil
 => nil
ruby-1.9.2-p180 :006 > GC.start
 => nil
ruby-1.9.2-p180 :007 > ObjectSpace.each_object(C){}
 => 0

因此不再存在对C的引用.好的.但是,用map{|x| x.foo} with map(&:foo)(广告上是等效的)代替它并不会被收集:

So no references to C exist anymore. Good. But substituting map{|x| x.foo} with map(&:foo) (which is advertised as equivalent), it doesn't get collected:

ruby-1.9.2-p180 :001 > a = 10.times.map{C.new}
 => [...]
ruby-1.9.2-p180 :002 > b = a.map(&:foo)
 => ["foo", "foo", "foo", "foo", "foo", "foo", "foo", "foo", "foo", "foo"]
ruby-1.9.2-p180 :003 > ObjectSpace.each_object(C){}
 => 10
ruby-1.9.2-p180 :004 > a = nil
 => nil
ruby-1.9.2-p180 :005 > b = nil
 => nil
ruby-1.9.2-p180 :006 > GC.start
 => nil
ruby-1.9.2-p180 :007 > ObjectSpace.each_object(C){}
 => 10
ruby-1.9.2-p180 :008 >

这是一个红宝石错误吗?我会尝试使用更多版本的ruby来确定,但这似乎是一个明显的问题.有人知道我在做什么错吗?

Is this a ruby bug? I'll try in more versions of ruby to be sure but this seems like an obvious issue. Anyone know what I'm doing wrong?

我已经在1.8.7-p352中进行了尝试,但没有问题. 1.9.3-preview1 确实,但是仍然存在问题.是按顺序报告错误还是我做错了什么?

I've tried this in 1.8.7-p352 and it doesn't have the issue. 1.9.3-preview1 does however still have the issue. Is a bug report in order or am I doing something wrong?

Edit2:格式化(为什么在每行前放置四个空格会产生语法高亮显示,而<pre>标签却不会?)

formatting (why does putting four spaces before each line produce syntax highlighting while <pre> tags don't?)

推荐答案

由于a.map(&:foo)应该与a.map{|x| x.foo}完全相同,因此看来您确实在Ruby代码中遇到了一个错误.在(http://redmine.ruby-lang.org/)上提交错误报告不会有任何伤害,最糟糕的是它可能会被忽略.您可以通过为该问题提供补丁来减少这种情况的发生.

As a.map(&:foo) should be the exact equivalent to a.map{|x| x.foo}, it seems like you really hit a bug in the Ruby code here. It cannot hurt to file a bug report on (http://redmine.ruby-lang.org/), the worst that can happen is that its being ignored. You can decrease the chances of that by providing a patch for the issue.

:我扔了我的IRB,并尝试了您的代码.我可以重现您在ruby 1.9.2p290 (2011-07-09 revision 32553) [x86_64-linux]上描述的问题.但是,在符号上显式调用to_proc不会遇到相同的问题:

I threw on my IRB and tried your code. I can reproduce the issue you describe on ruby 1.9.2p290 (2011-07-09 revision 32553) [x86_64-linux]. However, explicitely calling to_proc on the symbol does not suffer from the same problem:

irb(main):001:0> class C; def foo; end; end
=> nil
irb(main):002:0> a = 10.times.map { C.new }
=> [...]
irb(main):004:0> b = a.map(&:foo.to_proc)
=> [nil, nil, nil, nil, nil, nil, nil, nil, nil, nil]
irb(main):005:0> ObjectSpace.each_object(C){}
=> 10
irb(main):006:0> a = b = nil
=> nil
irb(main):007:0> GC.start
=> nil
irb(main):008:0> ObjectSpace.each_object(C){}
=> 0

似乎我们在这里面临隐式Symbol -> Proc转换的问题.也许以后我会尝试深入探讨Ruby源代码.如果是这样,我会及时通知您.

It seems we are facing an issue with the implicit Symbol -> Proc conversion here. Maybe I will try to dive a bit into the Ruby source later. If so, I will keep you updated.

该问题的简单解决方法:

Simple workaround for the problem:

class Symbol
  def to_proc
    lambda { |x| x.send(self) }
  end
end

class C
  def foo; "foo"; end
end

a = 10.times.map { C.new }
b = a.map(&:foo)
p b
a = b = nil
GC.start
p ObjectSpace.each_object(C) {}

打印0.

这篇关于Ruby Symbol#to_proc泄漏1.9.2-p180中的引用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆