当我运行它然后在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
运行此功能。
答案 0 :(得分:5)
a = nil
行是不必要的,您可以将其删除。
每次循环时你都会创建很多对象 - 两个字符串,两个哈希值和一个Activity对象,所以我不会感到惊讶你的内存使用率很高,特别是当你循环1000万次时!似乎没有更高效的内存来编写此代码。
我能想到的减少内存使用量的唯一方法是每 x 次迭代手动启动垃圾收集器。机会是Ruby的GC不够积极。但是,您不希望每次迭代都调用它,因为这会极大地降低代码速度。也许你可以使用每100次迭代作为起点并从那里开始。你必须分析和测试什么是最有效的。
GC is here的文档。
答案 1 :(得分:1)
我知道这是一个古老的问题,但我必须提出另一种激进的方法:
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对象。通常它不会受到伤害,但是因为在这种情况下它会伤害你,我认为你会用这种方式少用内存。