3

EF4 (System.Data.Entities、nuget パッケージなし) を使用し、LINQ クエリのコンテキストを直接ヒットするプロジェクトがあります。複数のユーザーをログインさせて (VS テスト負荷テストを使用して) 負荷テストを行うと、常にパフォーマンスが低下し、CPU が 100% に達し、VS.NET は .NET ロックの競合が多く、ガベージ コレクションが多いというアラートをスローします。

かなりのプロファイリングと微調整を行うと、すべてが LINQ クエリ自体の実行を指しているように見えます (ある程度予想されることです)。結果に配置します。

誰もこれを経験しましたか?何が原因で、どうすれば解決できますか? 何らかの理由で .ToList() 呼び出しをスレッド化する必要がありますか?

更新: 数人が詳細を求めてきました..ここに問題のコードがあります (リリースできないものを削除するために少し調整されています)。

var query =
            from f in context.fs
            where f.usr.Any((u) => u.id == id)
            select new
            {
                FS = f,
                f.fList,
                E = from e in f.fList select new { e.er },
                L = from l in f.fList select new { l.id }
            };
    var res = query.ToList();

高負荷下では、この同じコードが複数のスレッドで実行されます (プロファイラーは 13 と表示します)。ToList() 呼び出しは絶対的な殺人であり、ほぼすべての遅延の原因となっています。

4

2 に答える 2

2

IQueryableメソッドとIEnumerableメソッドは異なる実行を使用する ことを覚えておく必要があります。IQueryable特に、メソッドは通常、メモリ内の式ツリーを変更するだけです。プロファイラーの観点からは、それらが顕著な時間を取ることはありません。ToListクエリ (前のメソッドから生成された) が実際に実行されるのは呼び出しまでではありませんIQueryable。これは、実際のネットワーク IO が行われる場所であることを意味します。これに費やされる時間は、すべてのクエリ生成を合わせた時間よりも大幅に長くなります。

要するに、プロファイラーはここではあまり役に立ちません。すべての作業は を通じて行われToListますが、クエリの効率を決定するコードは基本的に他の場所にあります。あなたが望んでいるのは、本質的に高価な操作であるか、クエリを効率的に記述していない可能性があります (その場合、情報を提供するためにクエリについて詳しく知る必要があります)。

並列化が役立つかどうかについては、実際にはわかりません。私の推測では、おそらくそうではありません。CPU が使い果たされている場合は、CPU をビジー状態に保ち、スレッド化によってオーバーヘッドが増えて速度が低下するだけです。CPU がタスク化されていなくても遅い場合は、スレッド化が役立つ可能性が高くなります。

于 2012-09-21T15:03:03.913 に答える
0

クエリへ:完全なエンティティが必要な場合は、クエリの実行およびその後fListに射影を実行します。EL

var query = from f in context.fs
            where f.usr.Any((u) => u.id == id)
            select new
            {
                FS = f,
                f.fList
            };
var res = query.ToList();
foreach (var x in res)
{
    // runs in memory
    var E = from e in x.fList select new e.er;
    var L = from l in x.fList select new l.id;
    // ...
}

E と L のみが必要な場合は、それらを組み合わせます。

var query = from f in context.fs
            where f.usr.Any((u) => u.id == id)
            select new
            {
                FS = f,
                EL = from x in f.fList select new { e.er, l.id }
            };
var res = query.ToList();
于 2012-09-23T17:04:41.417 に答える