2009-04-02 38 views
5

エンティティフレームワークは、新しいオブジェクトをデータベースに挿入するときに過剰な量のメモリを使用するように見えます。エンティティフレームワークのメモリ使用率

for(int i = 0; i < numOwners; ++i) 
{ 
    var owner = Owner.CreateOwner(); 
    db.AddToOwnerSet(owner); 
    for(int j = 0; j < numChildren; ++j) 
    { 
     var child = Child.CreateChild(); 
     owner.Childs.Add(child); 
    } 
} 
db.SaveChanges(); 

この時点では、これらのオブジェクトにはほとんどデータ要素が含まれていません。これらのオブジェクトの140,000をデータベースに挿入すると、アプリケーションの合計メモリ使用量は600 MB、300,000に対して1.2ギガバイトでした。これらのオブジェクトは小さく、文字列名と整数キーだけです。

SaveChanges呼び出しをループに入れてメモリ使用量を減らすことはできますが、実行時間が非常に悪くなり、すでにかなり悪いです。

エンティティフレームワークが非常に多くのメモリを使用している理由、またはメモリを少なくする方法を知っていますか?

答えて

2

エンティティフレームワークは(多くのORMのように)データをメモリに保持するため、多くのインメモリコレクションと同様に、内部配列が存在する可能性があります。アイテムをコレクションに追加すると、内部配列の容量が倍になります。

たとえば、256個のアイテムを含むArrayListのようなコレクションがあり、そのアイテムに257番目のアイテムを追加すると、内部的には512個のアイテム配列に新しいメモリブロックが割り当てられます。新しい512項目の配列にコピーされ、256項目の配列がガベージコレクションに使用可能になります。したがって、移行ポイントでは、257番目のアイテムを追加しただけで768個のアイテムがメモリに割り当てられます。 memorystreamを使用しているときに私は頭痛に冒されました。なぜなら、本当に必要なものよりも3倍も多くの連続した断片化されていないメモリが必要だからです。これはコレクションに表示される.Capacityプロパティで、ほとんどの場合2の累乗です(必要に応じてサイズが2倍になるため)。

メモリオブジェクトのコレクションをサポートするために、必要に応じて2倍のサイズの内部配列があります。したがって、同じタイプの300,000個のオブジェクトは、おそらくサイズ524,288の内部配列に保持されます。さらに、.NEt Frameworkの他の場所でも同様のテクニックがあれば、262145番目の項目が追加されるたびに、項目が新しい配列にコピーされている間に262144と524288の配列がメモリ内に存在しました。合計786432個のアイテムがメモリに格納されます。ガベージコレクタがそれがもう必要ではないと判断するまで、古いアレイは固執するでしょう。

メモリ使用量を向上させる可能性のある同時実行性のサポートについては、Entityフレームワークにいくつかのオプションがあります。私はここでしか推測していませんが、並行性をサポートするためには、データの現在のバージョンと、並行性をサポートするための比較用のオリジナルバージョンの両方をメモリに格納します。

私はまた、あなたがどのデータをやりとりしているのかを調べます。照会され、メモリにロードされたものを制限する巧妙な基準を見つけようとする。たとえば、ユーザーが顧客アカウントを編集できるアプリケーションを持っていて、特定のアカウントのみが割り当てられている場合は、そのユーザーをフィルタリング条件として使用して、ユーザーが相互作用する可能性のあるアカウントのみをメモリに読み込みます。

1

あなたのオブジェクトは実際のデータの点では「小さい」かもしれませんが、各オブジェクトはDTOではありません - Entity Frameworkは各エンティティに大量の定型コードを添付します。つまり、大。

ラージオブジェクトグラフで一貫して作業する場合は、安定して成熟し、動作することが証明されたNHibernateのようなものを使用することを検討してください。エンティティフレームワークは、機能とパフォーマンスに関して非常に遅れています。

2

私はこれが古い質問であることを知っていますが、今日も同じ問題が発生していて、原因を突き止めることができました。

SQLスクリプトの生成が大きなメモリジャンプを引き起こしているように見えます。私は、ストアドプロシージャを作成してオブジェクトにリンクすることを確認しました(ただし、this articleのようにIDの値を返すようにしてください)、300Mバイト以上のメモリが節約されました。

関連する問題