テーブルに100レコードのStudent
という単純なActiveRecordモデルがあります。私は、レールのコンソールセッションで次の操作を行いますハッシュのActiveRecordオブジェクトはガベージコレクションされません - バグや一種のキャッシュ機能?
ObjectSpace.each_object(ActiveRecord::Base).count
# => 0
x = Student.all
ObjectSpace.each_object(ActiveRecord::Base).count
# => 100
x = nil
GC.start
ObjectSpace.each_object(ActiveRecord::Base).count
# => 0 # Good!
は今、私は次のようにします。
ObjectSpace.each_object(ActiveRecord::Base).count
# => 0
x = Student.all.group_by(&:last_name)
ObjectSpace.each_object(ActiveRecord::Base).count
# => 100
x = nil
GC.start
ObjectSpace.each_object(ActiveRecord::Base).count
# => 100 # Bad!
この問題が発生したと根本的に知らなくても、これを解決するスマートな方法があるかどうか、なぜ誰もが説明できますハッシュ構造?私はこれを行うことができます知っている:
x.keys.each{|k| x[k]=nil}
x = nil
GC.start
をし、それが正しくメモリからすべてのStudentオブジェクトを削除しますが、一般的な解決策がある場合、私は思ったんだけど(私の現実の問題が広く普及し、より複雑なデータを持っています上記のハッシュよりも構造が複雑です)。
私はRuby 1.9.3-p0とRails 3.1.0を使用しています。
UPDATE(解決しよう)
以下パーオスカー・デル・ベンの説明、いくつかのActiveRecord ::関連オブジェクトは(彼らは実際に両方のコードスニペットで作成されますが、問題のコードスニペットで作成されたいくつかの理由のために、彼ら第2のものでのみ「誤動作」があります。誰かがなぜその理由を明らかにすることができますか?)。これらは、@recordsというインスタンス変数を介してActiveRecordオブジェクトへの参照を保持します。このインスタンス変数は、ActiveRecord :: Relationの "reset"メソッドによってnilに設定できます。あなたはすべての関係オブジェクトでこれを実行することを確認する必要があります。
ObjectSpace.each_object(ActiveRecord::Base).count
# => 100
ObjectSpace.each_object(ActiveRecord::Relation).each(&:reset)
GC.start
ObjectSpace.each_object(ActiveRecord::Base).count
# => 0
注:それはコードよりもはるかに遅くなりますけれどもまた、(オスカー・デル・ベンが参照ruby-mass宝石を使用して)Mass.detachを使用することができます上記。上記のコードは、メモリからいくつかのActiveRecord :: Relationオブジェクトを削除しないことに注意してください。しかし、これらはかなり重要ではないようです。あなたはやって試すことができます:
Mass.index(ActiveRecord::Relation)["ActiveRecord::Relation"].each{|x| Mass.detach Mass[x]}
GC.start
そして、これはActiveRecordの::関係オブジェクトの一部を削除し、すべてではなく、それらのでしょう(わからない理由、そして残されたものは何Mass.references奇妙なを持っていません。)。
1.9または3.1に固有の場合があります - この動作はRails 3.0.7およびruby enterprise(ree 1.8.7)では表示されません。 – klochner
ありがとうございますKlochner! Ruby 1.8.7-p174でコードを実行しました。 Ruby 1.8.7では、Rails 3.0.7とRails 3.1.0の両方でオブジェクトの破壊が正しく処理されているようです。私。 2番目の例では、0個のオブジェクトを取得します。私もRuby 1.9.2を試しましたが、同じ問題は1.9.3と同じように起こります。あなたはYARVにバグがあると思いますか? – AmitA
私はRuby 1.8.7とRails 2.3.12でテストを行った。私はコンソールでのみテストし、同じ問題がありました。 ** **を除いて、 'asdasdsa 'のようなコンソールにゴミを書き、' NameError'を開始しました。この 'GC.start'の後にすべてがクリーンアップされました。好奇心の強い副作用かもっと重要なことがあるかどうかは不明です。 – Casper