Ruby:批量加载对象如何提高内存使用率?

时间:2015-06-20 14:36:43

标签: ruby-on-rails ruby performance

我是自学成才,对于将对象加载分成循环中的单独部分的术语或具体改进(如果有的话)不太确定。

例如,我使用rails,最近我遇到了一个问题,即我一次加载了太多重的ActiveRecord对象,并在rails API中找到了这个问题:http://api.rubyonrails.org/classes/ActiveRecord/Batches.html

find_in_batches的作用是将查询分成多个子集,因此不是制作一个大型查询,而是制作10个小查询,而不是一次加载这么多对象。

例如:

def batch_process
  Car.find_in_batches do |batch|
    batch.each(&:start_engine!)
  end # at the end of each iteration, is the memory from the current batch deallocated?
end

def start_all_at_once
  Car.all.each(&:start_engine!)
end

我的问题是,这样做有什么好处?从概念上讲,我理解一次加载较少允许在每个循环中释放内存(这是正确的??),但究竟是什么改进了?我相信这是最高内存消耗,但这是否会转化为RAM / CPU使用率的改进(不确定RAM / CPU之间的区别是诚实的)?或者与垃圾收集或Ruby堆大小有关?

试图了解较低级别的细节。谢谢!

1 个答案:

答案 0 :(得分:4)

假设您想要处理数据库中的100万条记录。

首先,您的数据库需要加载并向您的Ruby应用程序发送100万条记录。然后Rails需要解析那100万条记录(这会使用内存),然后生成100万条记录和一个包含所有内容的大数组。这将使用大量处理能力(CPU)和内存(RAM)来存储它们。

让我们说每条记录需要1KB的内存(这是一个任意数字)。然后100万将占用1GB内存,我们甚至不计算数据库使用的内存,传输和转换。

现在,分批加载100万条记录。然后,您的数据库一次只加载和传输1000条记录。 Ruby / Rails也是如此,它将使用1MB的内存。重复下一千条记录,将重用该内存。因此,您只使用前一个示例的一小部分RAM!