1

在关系上构建记录时,我遇到了占用太多内存的过程。在谈论这样的代码时应该预料到:

注意ScanItem是 Mongoid 文档和扫描has_many项目。

1000.times do
  item = scan.items.build
  item.save
end

我不需要这种关系来保存这些对象,所以我第一次尝试绕过它是这样的:

1000.times do
  item = Item.new(scan_id: scan.id)
  item.save
end

不幸的是,它产生了相同的结果。它不在垃圾收集中。这是一个快速测试:

class Foo
end

1000.times do |i|
  foo = Foo.new
  if i % 100 == 0
    ObjectSpace.garbage_collect 
    puts ObjectSpace.each_object(Foo).count 
  end  
end 

# => 1
# => 2
# => 2
# => 2
# => 2
# => 2
# => 2
# => 2
# => 2
# => 2

1000.times do |i|
  item = Item.new(scan_id: scan.id)
  item.save
  if i % 100 == 0
    ObjectSpace.garbage_collect 
    puts ObjectSpace.each_object(Item).count 
  end  
end 

# => 100
# => 200
# => 300
# => 400
# => 500
# => 600
# => 700
# => 800
# => 900
# => 1000

所以我的问题是如何使用关系的引用创建记录,而不会因scan.items持有这些对象的关系而导致内存膨胀?甚至可能吗?

编辑:

即使每隔一段时间重新加载scan一次reload方法也无济于事,WeakRef 也无济于事。

4

2 回答 2

2

该问题可能是由身份映射引起的。身份映射将文档存储在内存中,因此可以重复使用它们,而不是为同一个文档多次访问 db。在 Rails 中,身份映射在每次请求后都会自动清除,因此通常我们不会注意到内存消耗有太大差异。但是,当在请求-响应周期之外工作时,应该使用unit_of_work. 查看Mongoid:IdentityMap了解更多详情。

于 2012-05-09T18:57:15.437 回答
0

如果可能,我会尝试利用 ActiveRecords find_each

APi on ActiveRecord 的 Find Each

如果那不可行,那么我会做一个 find_in_batches。祝你好运!

于 2012-05-08T22:35:31.763 回答