J'ai une application console qui contient deux méthodes:Pourquoi cette méthode d'extension IEnumerable est-elle beaucoup plus lente qu'une autre méthode d'extension (plus simple) (qui ne fait qu'opérer l'entrée)?
public static IEnumerable<TSource>
FooA<TSource>(this IEnumerable<IEnumerable<TSource>> source)
{
return source.Aggregate((x, y) => x.Intersect(y));
}
public static IEnumerable<TSource>
FooB<TSource>(this IEnumerable<IEnumerable<TSource>> source)
{
foreach (TSource element in source.First())
{
yield return element;
}
}
Ce qu'il fait: les deux prennent une séquence de séquences, FooA
produire l'intersection ensemble de tous, puis revenir résultat. FooB
itérez simplement la première séquence.
Ce que je ne comprends pas: FooB
est plus de 10 fois plus lent que FooA
, alors que FooB
est en fait beaucoup plus simple (il n'y a pas appel à Intersect()
méthode).
Voici les résultats:
00:00:00.0071053 (FooA)
00:00:00.0875303 (FooB)
FooB
peut être beaucoup plus rapide en retournant directement source.First()
, de toute façon je décompilé Distinct
méthode utilisant ILSpy et trouvé exactement la même boucle de retour de rendement foreach:
private static IEnumerable<TSource> DistinctIterator<TSource>
(IEnumerable<TSource> source, IEqualityComparer<TSource> comparer)
{
Set<TSource> set = new Set<TSource>(comparer);
foreach (TSource current in source)
{
if (set.Add(current))
{
yield return current;
}
}
yield break;
}
également : dans le code que j'utilise je ne peux pas retourner source.First()
(je reçois CS1622). Ce que je montre ici est en fait un code beaucoup plus simple que je me suis déshabillé pour le débogage.
Code est ici que j'utilise pour le test:
List<List<int>> foo = new List<List<int>>();
foo.Add(new List<int>(Enumerable.Range(0, 3000*1000)));
Stopwatch sa = new Stopwatch();
sa.Start();
List<int> la = FooA(foo).ToList();
Console.WriteLine(sa.Elapsed);
Stopwatch sb = new Stopwatch();
sb.Start();
List<int> lb = FooB(foo).ToList();
Console.WriteLine(sb.Elapsed);
Ainsi, 'Intersect' n'est jamais appelé. Bon point. Je n'y ai pas pensé. Il n'explique pas qu'il sera toujours beaucoup plus rapide que 'FooB' cependant – tigrou
Voir ma réponse d'où vient la différence. –