I made a function to recursively find the first or standard element that matches the condition (first block of code).
Resharper suggested that I change several lines in only one LINQ line (second block of code).
I was wondering if the Resharper suggestion could give me the same performance and the same amount of memory. I did a performance test (3rd block of code). The result is exactly what I expected. Why is the difference so big?
8156 milliseconds
Laure
23567 milliseconds
Laure LINQ
Where does this difference come from ??? Why don't the results match? ... or at least closer?
public static T RecursiveFirstOrDefault<T>(this T item, Func<T, IEnumerable<T>> childrenSelector, Predicate<T> condition)
where T : class
{
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;
}
But Resharper suggested that I convert the foreach block to a LINQ query as follows:
public static T RecursiveFirstOrDefaultLinq<T>(this T item, Func<T, IEnumerable<T>> childrenSelector, Predicate<T> condition)
where T : class
{
if (item == null)
{
return null;
}
if (condition(item))
{
return item;
}
return childrenSelector(item).Select(child => child.RecursiveFirstOrDefaultLinq(childrenSelector, condition)).FirstOrDefault(result => result != null);
}
Test:
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");
}
I need to go today ... I hope to answer the tests correctly: x86, Release on a 12-core computer, Windows 7, Framework.Net 4.5,
My conclusion:
~ 3 non linq. LINQ, , , , ( - ). LINQ , .
: