1

リレーションにレコードを作成するときに、メモリを大量に消費するプロセスが発生しています。このようなコードについて話すとき、それは予想されるべきです:

ScanおよびItemは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

この問題は、IDマップが原因である可能性があります。IDマップはドキュメントをメモリに保存するため、同じドキュメントに対してdbを複数回押す代わりに再利用できます。Railsでは、IDマップはリクエストごとに自動的にクリアされるため、通常、メモリ消費量に大きな違いはありません。ただし、要求と応答のサイクル外で作業する場合は、を使用する必要がありますunit_of_work。詳細については、Mongoid:IdentityMapをご覧ください。

于 2012-05-09T18:57:15.437 に答える
0

可能であれば、ActiveRecords find_each を活用しようと思います

ActiveRecord の Find Each の API

それができない場合は、find_in_batches を実行します。幸運を!

于 2012-05-08T22:35:31.763 に答える