创建许多新对象时内存膨胀



当我运行它,然后在OSX活动监视器中观察我的Ruby进程的内存消耗时,内存以大约3 MB/s的速度增加。

如果我删除事务,它的内存消耗大约减半,但内存占用量仍在不断上升。我的生产应用程序出现问题,Heroku 因其内存消耗而终止进程。

有没有办法以不增加内存的方式执行以下操作?如果我注释掉.save行,那没关系,但当然这不是解决方案。

ActiveRecord::Base.transaction do
  10000000.times do |time|
    puts "---- #{time} ----"
    a = Activity.new(:name => "#{time} Activity")
    a.save!(:validate => false)
    a = nil
  end
end

我正在使用delayed_job运行它。

a = nil行是不必要的,您可以将其删除。

每次循环时都会创建很多对象 - 两个字符串、两个哈希和一个 Activity 对象,所以我并不惊讶您遇到高内存使用率,尤其是当您循环 1000 万次时!似乎没有比内存效率更高的方法来编写此代码。

我能想到的减少内存使用量的唯一方法是每x次迭代手动启动垃圾回收器。Ruby的GC可能不够激进。但是,您不希望每次迭代都调用它,因为这会从根本上减慢您的代码速度。也许你可以使用每 100 次迭代作为起点,然后从那里开始。您必须分析和测试最有效的方法。

GC 的文档在这里。

我知道

这是一个古老的问题,但我必须提出另一种激进的方法:

ActiveRecord::Base.transaction do
  10000000.times do |time|
    puts "---- #{time} ----"
    sql = <<SQL
INSERT INTO activities ("name") VALUES ("#{time}")
SQL
    Activity.connection.execute(sql)
  end
end

关键是,如果插入如此简单,并且您已经跳过了任何ActiveModel验证,那么首先就没有理由实例化activerecord对象。通常它不会伤害,但由于在这种情况下它会伤害你,我认为你会以这种方式使用更少的内存。

最新更新