2013-02-14 24 views
0

我有一个回报率的应用程序和一个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。

回答

2

您应该使用像#find_each#find_in_batches这样的方法。这些将一次只加载一小部分记录。看看ActiveRecord::Batches

+0

感谢这就是我需要:) – 2013-02-14 18:36:23

2

我建议使用find_each,它可以批量生成对象。

此外,还需要在SQL如果可能有内循环状态,所以ActiveRecord的不必实例化对象(因此使用内存)你不使用反正:

Model.find_each(:conditions => {:my => :condition}).each do |m| 
    # do something 
end 
+0

感谢您的条件解释) – 2013-02-14 18:37:04

1

你可以试试下面的方法:

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 
+0

谢谢。有趣的解决方案,但我认为这与批处理find_each类似。 – 2013-02-14 18:39:03

+0

find_each是否解决了您的问题?我发现有时候GC不能清理内存,而我的内存使用量仍然会增长。 – 2013-02-14 18:58:08

+0

是的,'find_each'很好。您可以通过选项'.find_each(:batch_size => 100)'指定批处理大小(通过批处理默认大小为1000)。 – 2013-02-14 19:10:30