2011-08-08 7 views
13

当社では、コアにやや大きなビジネスデータオブジェクトを持つ新しいアプリケーションを開発しています。アプリケーションからデータベースを抽象化するためにまずEntity Frameworkをコードで試してみることにしましたが、状況は間違っていました。ビジネスオブジェクトは約60のクラスで構成され、合計約600のプロパティがあります。しかし、それは木構造であり、クロスオーバ/バックトラックポインタは存在しない。Entity Framework 4.1リリースでCode-Firstを使用するとパフォーマンスが極端に低下します

私たちのテストでは、クラスの初期化されていないインスタンスをデータベースに追加しました。データ構造上でDbContext.Addを使用すると、開発マシンで8分かかりました。このサイズのオブジェクトの予想されるパフォーマンスですか? Entity Frameworkのパフォーマンスが低下する一般的な問題の一覧はありますか?私はこれにいくつかの助けが必要だと思う。

さらにいくつかのデータ・ポイント:ビジネス・オブジェクトのルートの下の第1レベルに27のエレメントがあります。 3つの要素が存在する(残りはコメントアウトされています)、追加する時間は4.5秒です。 5つの要素がある場合、11.8秒です。 8つの要素がある場合、1分12.5秒です。明らかに、これらの要素のサイズは大きく異なりますが、これらはある種の体系的な問題を示すようです。

+3

SQLプロファイラで生成したSQLを見ましたか?時々、EFがSQLを調べることによって何をしようとしているかについて、多くのことを集めることができます。私の意見では、関連する60のクラスをdbに保存するのは、EFの1秒未満の操作でなければなりません。 – automagic

+0

私たちはそれを試していませんでした。なぜなら、最後にデータベースを叩くだけで、すべての処理がEF内で行われていたからです。トレースは非常に大きいです...私は私が何を探していなければならないのかよく分かりません。 – dythim

+1

コンテキストを作成して再度測定するときに 'dbContext.Configuration.AutoDetectChangesEnabled = false; 'を設定してみてください。 'Add'は遅いと言うので(' SaveChanges'ではなく)、私は自動変更の検出/スナップショットの作成が遅くなると思っています。 – Slauma

答えて

3

だから、問題を理解しました。 NHibernateを進めていくうちに、いくつかの実験的なコードである構造的なエラーに遭遇しました。カテゴリは、その子のPropertyChangedイベントを購読していたため、NHibernateがクラッシュしました。

どちらが良いですか!それは実際に問題があると私たちに言った。エンティティ・フレームワークは、何か問題を起こす可能性があるという兆候なしに永久に稼動しました。

とにかく、私たちは当面はNHibernateを使い続けるつもりです。私たちは、それを使って得たデータベース構造に対して、私たちが持っているコントロールが好きです。

4

...私たちのテストでは、データベースへのクラス のシングル、初期化されていないインスタンスを追加することでした。 DbContext.Addを使用して...

あなたはあなたのコード・ファーストモデルはあなたがAddと呼ばれてきた前にメモリに作成され、ロードされていることを確認しましたか?私は、次の意味:あなたはこのようなテストコードを使用している場合...

using (var context = new MyContext()) 
{ 
    var myHugeBusinessObject = CreateItSomeHow(); 

    context.HugeBusinessObjects.Add(myHugeBusinessObject); 

    context.SaveChanges(); 
} 

を...、それはあなたがあなたのテストアプリケーションAddにコンテキストを使用している最初の時間は、実際に構築するためのいくつかの時間を費やしますですEFモデルをメモリに格納してから、オブジェクトをコンテキストに追加します。

あなたが好きなインスタンス何かのために、単にAddを呼び出す前に、ダミーメソッドを追加することによって、これらの2つのステップを分離することができます。これにより

public class MyClass 
{ 
    public int Id { get; set; } 
    public string P1 { get; set; } 
    // ... P2 to P49 
    public string P50 { get; set; } 
    public MyClass Child1 { get; set; } 
    // ... Child1 to Child26 
    public MyClass Child27 { get; set; } 
} 

私が作成した:

context.HugeBusinessObjects.Count(); 

私がテストを構築しましたオブジェクト:

var my = new MyClass(); 
MyClass child = my; 
for (int i = 0; i < 100; i++) 
{ 
    child.Child1 = new MyClass(); 
    child = child.Child1; 
} 
child = my; 
for (int i = 0; i < 100; i++) 
{ 
    child.Child2 = new MyClass(); 
    child = child.Child2; 
} 
// and so on up to Child27 

このオブジェクトグラフには2700個の子オブジェクトがありますそれぞれ50スカラーのプロパティ。それから私はこのコードをテストした:

using (var context = new MyContext()) 
{ 
    var my = CreateWithTheCodeAbove(); 

    context.MyClassSet.Count(); 
    context.MyClassSet.Add(my); 

    context.SaveChanges(); 
} 

...Count()(= EFモデルを構築する)おおよそ25秒を必要とします。 Addが必要です1秒です。 (上記のループで100から1000を変更すると(グラフの中に27000個のオブジェクトがある場合)Addの時間はほぼ直線的に9-10秒に増加します)。この結果は、AutoDetectChangesEnabledからtrueまたはfalseには依存しません。)

次の興味深い結果:私はMyClassにサンプルコードでモデル(Count()の構築と一緒に過ごした時間)140秒に爆発をより20のナビゲーションプロパティ(Child47からChild28)を追加した場合。 Addの継続時間は、追加のプロパティとともに直線的に増加するだけです。

私の仮説は次のとおりです。コンテキストにビジネスオブジェクトを追加する時間は実際には測定されませんが、EFモデルをメモリに組み込む必要がある時間です。モデルを構築する時間は、モデルの複雑さに伴って指数関数的に増加するように見えます。クラスのナビゲーションプロパティの数とおそらく異なる関与クラスの数。

これらのステップを分離するには、上記のようなダミーコールを使用します。あなたはすでにこの分離を持っているなら... omg、この投稿を忘れてください。

+0

あなたの提案は実際に多くのパフォーマンスを改善しました!私のコンピュータからの時間は私の最初の投稿のように8分だったから、2.5分まで、必要な時間は他の開発者のマシンのいずれかに落ちました。これは大きな違いです。残念ながら、それはまだ生産準備ができていません...しばらくの間、私たちはNHibernateを見始めていますが、まだEFを念頭に置いています。私はあなたが実際にEFの内部構造を初期化することから来る遅れについてあなたが言ったことを理解しますが、それほど大きな差をつけるべきではないと分ける理由は分かりません。 – dythim

+0

私は、テストに使用できるコードの単純化モデルを作成しようとします(上記のLadislavが示唆したように)。 – dythim

+0

@dythim: 'Total(* Count()+ Add()')は 'Add()'だけを呼び出したときの半分の時間になりましたか?はいの場合は、私も期待していないことです。私は時間が同じだが不均等に分布していると予想していた。 'Count()'(=モデルの作成)は 'Add()'よりもはるかに遅い。あなたは、合計だけでなく、それぞれの呼び出しの時間をチェックしましたか?内部モデル構造は、*アプリケーション*インスタンスごとに1回のみ作成されます。モデルの作成がパフォーマンス上の問題である場合、あなたの質問は別のものに変わります(モデルの初期化のパフォーマンスを向上させる方法)。 – Slauma

関連する問題