查看我今天使用性能分析器處理的一段web應用程序。我認爲一個聯盟造成了一些延誤,但是卻發現了其他令人驚訝的結果。FirstOrDefault的性能()
放緩原因之一似乎是FirstOrDefault。
這是一個非常簡單的LINQ查詢是這樣的:
foreach(Report r in reports)
IDTOStudy study = studies.FirstOrDefault(s => s.StudyID == r.StudyID);
我創建了一個小方法來複制我想通FirstOrDefault在做的行爲。
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:
一個附加一點我注意到的是,剖析說,我即將用盡我的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; }
}
}
如果您正在使用LINQ to SQL或EF,然後'FirstOrDefault()'應該簡單地生成'TOP 1'查詢 –
什麼是研究,它是一個orm對象(例如來自Entity Framework或類似的dbset)? –
@lazyberezovsky我懷疑是第一個例子生成O(n)和第二個O(1)db查詢 –