webappのセクションを見ると、今日はパフォーマンスプロファイラーで作業しています。私は、連合がいくつかの遅れを引き起こしていると思ったが、代わりに他の驚くべき結果を見出した。FirstOrDefault()のパフォーマンス
減速の原因の1つがFirstOrDefaultであるように見えました。
それはこのように見えた非常に単純なLINQクエリだった:私はFirstOrDefaultをやっていた考え出し行動を複製する小さなメソッドを作成し
foreach(Report r in reports)
IDTOStudy study = studies.FirstOrDefault(s => s.StudyID == r.StudyID);
。
private IDTOStudy GetMatchingStudy(Report report, IList<IDTOStudy> studies)
{
foreach (var study in studies)
if (study.StudyID == report.StudyID)
return study;
return null;
}
このメソッドは、このように見えるFirstOrDefaultを置き換える:
foreach(Report r in reports)
IDTOStudy study = GetMatchingStudy(r, studies);
は、パフォーマンス・プロファイラを実行している新しいコードを見てみると、私の新しい方法として、完了するまでに長いと二回取るためにFirstOrDefault
を示しました。これは衝撃的なものでした。
FirstOrDefault()
クエリで間違ったことを行う必要があります。それは何ですか?
FirstOrDefault()
はクエリ全体を完了してから最初の要素を取りますか?
これをスピードアップしてFirstOrDefault()
を使用するにはどうすればよいですか?
編集1:私が気づい
1つの追加点は、プロファイラが、私はこれらの実装の両方に私のCPUを限界いっぱいまでだと言うことです。それは私が気にしないし、期待していないものでもあります。私が追加した追加の方法では、スパイクを減らすことはできず、その持続時間を半分に短縮しました。
編集3:
辞書に研究を置くには、途方もなく実行時間を改善しました。コミットされたコードがどのように見えるかは間違いありません。しかし、FirstOrDefaultの質問には答えません。
編集2:
ここでは、簡単なコンソールアプリケーションで要求されたサンプルコードです。私の走りは、FirstOrDefaultの方が長くかかる場合がほとんどです。私は何が起こっていると思う何
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reactive.Linq;
using System.Reactive.Concurrency;
using System.Diagnostics;
namespace TestCode
{
public class Program
{
public List<IntHolder> list;
public static void Main(string[] args)
{
var prog = new Program();
prog.list = new List<IntHolder>();
prog.Add50000Items();
prog.list.Add(new IntHolder() { Num = 12345 });
prog.Add50000Items();
var stopwatch = new Stopwatch();
stopwatch.Start();
prog.list.FirstOrDefault(n => n.Num == 12345);
stopwatch.Stop();
Console.WriteLine("First run took: " + stopwatch.ElapsedTicks);
var lookingFor = new IntHolder() { Num = 12345 };
stopwatch.Reset();
stopwatch.Start();
prog.GetMatching(lookingFor);
stopwatch.Stop();
Console.WriteLine("Second run took: " + stopwatch.ElapsedTicks);
Console.ReadLine();
}
public void Add50000Items()
{
var rand = new Random();
for (int i = 0; i < 50000; i++)
list.Add(new IntHolder() { Num = rand.Next(100000) });
}
public IntHolder GetMatching(IntHolder num)
{
foreach (var number in list)
if (number.Num == num.Num)
return number;
return null;
}
}
public class IntHolder
{
public int Num { get; set; }
}
}
ようなもので舞台裏で起こってデータベースクエリをチェックアウトすることにより、この理論を証明することができ、その後、 'FirstOrDefaultは()'単に 'TOPを生成する必要があります '1'クエリ –
調査は何ですか、ormオブジェクト(Entity Frameworkなどのdbset)ですか? –
@ lazyberezovsky私の疑念は、最初の例ではO(n)と2番目のO(1)dbクエリを生成することです。 –