2013-05-27 11 views
14

Pracuję na tablicę, która i muszę nad tym zapętlić. Po pierwsze, używam lambda ForEachDlaczego pętla na obiekcie tablicy z `foreach` jest szybsza niż lambda` ForEach`?

Array 
.ForEach<int>(array, (int counter) => { 
    Console.WriteLine(counter); 
}); 

a potem użyć prostego foreach. Uważam, że prosty foreach jest szybszy niż Lambda ForEach, ale kiedy testuję go z ogólnymi listami, ForEach jest szybszy niż prosty foreach.

dlaczego pętla na obiekcie tablicy z foreach jest szybsza niż lambda ForEach? Aktualizacja: Testuję na macierze

+0

rzeczą, którą nazywamy lambda foreach w rzeczywistości wdrożenie oceny leniwy, więc nie ma dużo dodatkowego kodu. – vittore

+14

Pokaż swoje przypadki testowe. –

+1

znalazłem przeciwnego moim teście –

Odpowiedz

4

edytowany kod Keitha nieco - Na moim komputerze foreach wykonano około sześć razy szybciej niż Array.ForEach:

class Program 
{ 
    static void Main(string[] args) 
    { 
     Benchmark(50); 
    } 

    private static void Benchmark(int iterations) 
    { 
     int[] list = Enumerable.Range(0, 100000000).ToArray(); 

     long sum = 0; 
     for (int i = 0; i < iterations; i++) 
     { 
      sum += ArrayForeach(list); 
     } 

     Console.WriteLine("ForEach " + sum/iterations); 

     sum = 0; 
     for (int i = 0; i < iterations; i++) 
     { 
      sum += Foreach(list); 
     } 

     Console.WriteLine("foreach " + sum/iterations); 
    } 

    private static long Foreach(int[] list) 
    { 
     long total = 0; 
     var stopWatch = Stopwatch.StartNew(); 
     foreach (var i in list) 
     { 
      total += i; 
     } 
     stopWatch.Stop(); 
     return stopWatch.ElapsedTicks; 
    } 

    private static long ArrayForeach(int[] list) 
    { 
     long total = 0; 
     var stopWatch = Stopwatch.StartNew(); 
     Array.ForEach(list, x => total += x); 
     stopWatch.Stop(); 
     return stopWatch.ElapsedTicks; 
    } 
} 

Na moim komputerze (który może uruchomić inne CLR niż inne), które produkuje (w wydaniu):

ForEach 695910 
foreach 123852 

W Debug:

ForEach 941030 
foreach 845443 
  • To pokazuje, że foreach cieszy pewne optymalizacje kompilatora, myślę głównie w dostępie do listy w pamięci.
  • W debugowaniu wygląda na obciążenie związane z uruchomieniem lambda, a za różnicę odpowiada podanie liczby (według wartości).

I sugerują, że ktoś więcej czasu spojrzeć z reflektorem ...

4

Bardziej szybko znajduję lambdę w moich testach. Skopiuj wklejanie kodu stopera MSDN i dekoruj go dwiema wersjami iteracji listy .... (Zmieniłem też kolejność, w której test jest pierwszy, a otrzymuję te same wartości czasowe). Bazująca na Linq iteracja z lambdą przebiega szybciej.

Lambda 00:00:00.49 
foreach 00:00:00.58 

a kod ..

var list = Enumerable.Range(0, 100000000).ToArray(); 
     var total = 0; 
     var stopWatch = new Stopwatch(); 
     stopWatch.Start(); 
     Array.ForEach(list, x => total += x); 

     stopWatch.Stop(); 
     TimeSpan ts = stopWatch.Elapsed; 
     string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}", 
      ts.Hours, ts.Minutes, ts.Seconds, 
      ts.Milliseconds/10); 
     Console.WriteLine("RunTime " + elapsedTime); 


     stopWatch = new Stopwatch(); 
     stopWatch.Start(); 
     foreach (var i in list) 
     { 
      total += i; 
     }  
     stopWatch.Stop(); 
     // Get the elapsed time as a TimeSpan value. 
     ts = stopWatch.Elapsed; 

     // Format and display the TimeSpan value. 
     elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}", 
      ts.Hours, ts.Minutes, ts.Seconds, 
      ts.Milliseconds/10); 
     Console.WriteLine("RunTime " + elapsedTime);    
+0

użytku na tablicy –

+0

lambda szybszym dla obu, ale lambda nadal wygrywa –

+1

, ile szybciej? Umysł ujawniający szczegółowe dane w zaktualizowanym poście? – David