2013-02-14 27 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