小编Ken*_*mon的帖子

Ruby Symbol#to_proc泄漏了1.9.2-p180中的引用?

好的,这是我第二次尝试使用我的Sinatra应用调试内存问题.我相信这次我把它固定成简单的示例代码.

似乎当我过滤一个数组时.map(&:some_method),它会导致该数组中的项目不被垃圾收集.运行等效.map{|x| x.some_method}的完全没问题.

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

class C
  def foo
    "foo"
  end
end
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

所以不再存在对C的引用.好.但是替换map{|x| x.foo} with …

ruby memory-leaks

5
推荐指数
1
解决办法
369
查看次数

MySQL datamapper适配器链接查询而不是加入

我正在使用DataMapper(ruby gem)作为mysql数据库的ORM.(dm-core 1.1.0,do-mysql-adapter 1.1.0,do_mysql 0.10.6)

我正在编写一个包含两个表的应用程序:一段时间内磁盘使用情况的日志,以及一个"当前用法"表,其中包含具有"最新"磁盘使用情况的外键,以便于参考.DataMapper类是QuotaLatestQuota,带有一个简单的模式:

class Quota
  include DataMapper::Resource

  property :unique_id, Serial, :key => true
  property :percentage, Integer
  ... (more properties)
end

class LatestQuota
  include DataMapper::Resource
  belongs_to :quota, :key => true
end

在我的代码中,我想找到LatestQuota表中与百分比高于95的配额相对应的所有条目.我正在使用以下datamapper查询:

quotas = LatestQuota.all(:quota => {:percentage.gte => threshold})
...later...
quotas.select{|q| some_boolean_function?(q)}

some_boolean_function是以DataMapper无法知道的方式过滤掉结果的东西,因此我需要调用ruby的select().

但它最终调用以下SQL查询(从DM的调试输出报告:)

SELECT `unique_id` FROM `quota` WHERE `percentage` >= 95

然后:

SELECT `quota_unique_id` FROM `latest_quota` 
WHERE `quota_unique_id` IN (52, 78, 82, 232, 313, 320…. all the unique id's from the above query...) …

ruby mysql datamapper

2
推荐指数
1
解决办法
655
查看次数

类相互引用的内存泄漏

对于好奇:事实证明我的内存泄漏与我在这里放入的样本无关.我认为我的问题已经解决了一些示例代码,但我的示例代码有不同的问题.我最终找到了我的真正问题,而且就在这里:Ruby Symbol#to_proc泄漏了1.9.2-p180中的引用?

我有两个红宝石类(GeneratorMember,在该示例中),其中发电机用作工厂(在术语的宽泛的定义)的成员对象,并且每个部件保持到它构成发电机的参考.

码:

class Generator
  def new_member
    Member.new
  end
end

class Member
  attr_reader :generator

  def self.get(generator)
    @generator = generator
    puts "Provided generator: #{generator}"
    generator.new_member
  end
end

使用IRB,我希望如果我只是调用我只是调用Member.get(Generator.new),但实际上并没有将结果赋给任何东西,那么对新构造的Generator对象的引用和新构造的Member对象都应该有零引用.所以垃圾收集器应该收集这两个对象.但它只收集会员,让发电机坐在附近:

ruby-1.9.2-p180 :001 > Member.get(Generator.new)
Provided generator: #<Generator:0x007fcf398015c8>
 => #<Member:0x007fcf39801550>
ruby-1.9.2-p180 :006 > GC.start
 => nil 
ruby-1.9.2-p180 :007 > ObjectSpace.each_object(Member){|m| puts m}
 => 0 
ruby-1.9.2-p180 :008 > ObjectSpace.each_object(Generator){|g| puts g}
#<Generator:0x007fcf398015c8>
 => 1

(ObjectSpace.each_object据我所知,它返回一个仍然在ruby堆上的给定类的引用列表.)

为什么仍然存在对坐在的Generator对象的引用?我没有以任何方式将它保存到变量中,所以不应再有任何引用它的东西了.收集了Member对象,因此引用Generator类的实例变量不应该阻止它被收集.

我也不仅仅是好奇.我们有一个具有类似类结构的Sinatra应用程序,等效的Generator类存储了一个巨大的Member对象缓存,每个请求有几百兆,并且它永远不会被收集.Ruby内存不足,应用服务器必须重启每十几个请求.

ruby garbage-collection

2
推荐指数
1
解决办法
704
查看次数