我有一个回报率的应用程序和一个cron耙任务,是这样的:红宝石减少内存使用RoR中的脚本
Model.all.each do |m|
if m < some_condition
m.do_something
m.save
end
end
Model
有1 000 000条记录(200万用可接受的条件)。有什么方法可以改善任务内存使用情况吗?它需要千兆字节的内存,并且Ruby进程被生产服务器所杀死。我的数据库是PostgreSQL。
我有一个回报率的应用程序和一个cron耙任务,是这样的:红宝石减少内存使用RoR中的脚本
Model.all.each do |m|
if m < some_condition
m.do_something
m.save
end
end
Model
有1 000 000条记录(200万用可接受的条件)。有什么方法可以改善任务内存使用情况吗?它需要千兆字节的内存,并且Ruby进程被生产服务器所杀死。我的数据库是PostgreSQL。
您应该使用像#find_each
和#find_in_batches
这样的方法。这些将一次只加载一小部分记录。看看ActiveRecord::Batches。
我建议使用find_each
,它可以批量生成对象。
此外,还需要在SQL如果可能有内循环状态,所以ActiveRecord的不必实例化对象(因此使用内存)你不使用反正:
Model.find_each(:conditions => {:my => :condition}).each do |m|
# do something
end
感谢您的条件解释) – 2013-02-14 18:37:04
你可以试试下面的方法:
def with_gc(enum)
count = enum.count
limit = 100
(0..count).select{|i| i % limit == 0}.each do |index|
new_count = enum.count
raise "query depends on updated param. Expected count #{count}, got #{new_count}" if count != new_count
enum.skip(index).limit(limit).each do |record|
yield record
end
GC.start
end
end
,你可以使用它像这样:
with_gc(Model.all) do |m|
if m < some_condition
m.do_something
m.save
end
end
谢谢。有趣的解决方案,但我认为这与批处理find_each类似。 – 2013-02-14 18:39:03
find_each是否解决了您的问题?我发现有时候GC不能清理内存,而我的内存使用量仍然会增长。 – 2013-02-14 18:58:08
是的,'find_each'很好。您可以通过选项'.find_each(:batch_size => 100)'指定批处理大小(通过批处理默认大小为1000)。 – 2013-02-14 19:10:30
感谢这就是我需要:) – 2013-02-14 18:36:23