【问题标题】:Reduce memory usage of ruby in RoR script减少 RoR 脚本中 ruby​​ 的内存使用量
【发布时间】:2013-02-14 15:15:38
【问题描述】:

我有一个 RoR 应用和一个 cron rake-task,类似于:

Model.all.each do |m|
  if m < some_condition
    m.do_something
    m.save
  end
end

Model 有 1 000 000 条记录(以及 200 000 条可接受的条件)。有什么方法可以提高任务内存使用率?它需要千兆字节的内存,并且 Ruby 进程在生产时被服务器杀死。我的数据库是 PostgreSQL。

【问题讨论】:

    标签: ruby ruby-on-rails-3 memory-management


    【解决方案1】:

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

    【讨论】:

    • 谢谢!这就是我需要的:)
    【解决方案2】:

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

    另外,如果可能的话,应用你在 sql 循环中的条件,这样 ActiveRecord 就不必实例化你不使用的对象(因此使用内存):

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

    【讨论】:

    • 感谢条件解释)
    【解决方案3】:

    您可以尝试以下方法:

      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 的批处理。
    • find_each 解决了您的问题吗?我发现有时 GC 不会清理内存,我的内存使用量仍然会增长。
    • 是的,find_each 很好用。您可以使用选项.find_each(:batch_size =&gt; 100) 指定批量大小(默认批量大小为 1000)。
    猜你喜欢
    • 2012-06-15
    • 1970-01-01
    • 2020-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-08
    • 2012-01-20
    • 1970-01-01
    相关资源
    最近更新 更多