我做了一個遞歸查找符合條件的第一個或默認項目(第一個代碼塊)的函數。此LINQ性能來自哪裏?
Resharper建議我只在一條LINQ行(第二個代碼塊)中更改幾行。
我想知道如果Resharper的建議會給我相同的性能和相同的內存佔用。我對性能進行了測試(第3代碼塊)。結果就是我所期望的。爲什麼差異如此之大?
8156 milliseconds
Laure
23567 milliseconds
Laure LINQ
從哪裏來的差異???爲什麼結果不一樣?......或者至少更接近?
public static T RecursiveFirstOrDefault<T>(this T item, Func<T, IEnumerable<T>> childrenSelector, Predicate<T> condition)
where T : class // Hierarchy implies class. Don't need to play with "default()" here.
{
if (item == null)
{
return null;
}
if (condition(item))
{
return item;
}
foreach (T child in childrenSelector(item))
{
T result = child.RecursiveFirstOrDefault(childrenSelector, condition);
if (result != null)
{
return result;
}
}
return null;
}
但ReSharper的建議我在foreach塊轉換爲LINQ查詢如下:
public static T RecursiveFirstOrDefaultLinq<T>(this T item, Func<T, IEnumerable<T>> childrenSelector, Predicate<T> condition)
where T : class // Hierarchy implies class. Don't need to play with "default()" here.
{
if (item == null)
{
return null;
}
if (condition(item))
{
return item;
}
// Resharper change:
return childrenSelector(item).Select(child => child.RecursiveFirstOrDefaultLinq(childrenSelector, condition)).FirstOrDefault(result => result != null);
}
測試:
private void ButtonTest_OnClick(object sender, RoutedEventArgs e)
{
VariationSet varSetResult;
Stopwatch watch = new Stopwatch();
varSetResult = null;
watch.Start();
for(int n = 0; n < 10000000; n++)
{
varSetResult = Model.VariationRef.VariationSet.RecursiveFirstOrDefault((varSet) => varSet.VariationSets,
(varSet) => varSet.Name.Contains("Laure"));
}
watch.Stop();
Console.WriteLine(watch.ElapsedMilliseconds.ToString() + " milliseconds");
Console.WriteLine(varSetResult.Name);
watch.Reset();
varSetResult = null;
watch.Start();
for(int n = 0; n < 10000000; n++)
{
varSetResult = Model.VariationRef.VariationSet.RecursiveFirstOrDefaultLinq((varSet) => varSet.VariationSets,
(varSet) => varSet.Name.Contains("Laure"));
}
watch.Stop();
Console.WriteLine(watch.ElapsedMilliseconds.ToString() + " milliseconds");
Console.WriteLine(varSetResult.Name + " LINQ");
}
我必須去...今天希望能正確回答測試:x86,在12核心機器上發佈,Windows 7,Framework.Net 4.5,
我的結論:
在我的情況下,它是非linq版本的約3倍。在LINQ中,可讀性更好,但是在圖書館中,只要記住它的功能和如何調用它(在這種情況下 - 不是絕對的一般情況)。 LINQ幾乎總是比好的編碼方法慢。 我會personnaly味:
- LINQ:如果性能是不是真的在 具體項目代碼的問題(大多數情況下)
- 非LINQ的:在性能是具體項目的代碼的問題,其中使用一個庫和代碼應該是穩定和固定的方法的使用應該有據可查,我們 不應該真的需要挖掘內部。
底層編譯器編譯的linq代碼和foreach代碼有很大不同,這就是你的區別所在。 – 2014-09-03 18:05:07
您是否必須重置計時器以獲得第二次測試迭代的正確計數? – entropic 2014-09-03 18:05:41
@entropic,謝謝... :-(!!!!! – 2014-09-03 18:06:41