2013-07-18 15 views
5

Podczas pracy nad projektem natrafiłem na poniższy fragment kodu, który podniósł flagę wydajności.pętla foreach Różnica wydajności listy

foreach (var sample in List.Where(x => !x.Value.Equals("Not Reviewed"))) 
{ 
    //do other work here 
    count++; 
} 

postanowiłem uruchomić kilka szybkich testów porównujących pierwotną pętli do następnego pętli:

foreach (var sample in List) 
{ 
    if (!sample.Value.Equals("Not Reviewed")) 
    { 
     //do other work here 
     count++; 
    } 
} 

i odrzucił tę pętlę w zbyt zobaczyć, co się dzieje:

var tempList = List.Where(x => !x.Value.Equals("Not Reviewed")); 
foreach (var sample in tempList) 
{ 
    //do other work here 
    count++; 
} 

Zapełniłem także oryginalną listę na 3 różne sposoby: 50-50 (czyli 50% wartości, w których "Nie znaleziono", a pozostałe pozostałe), 10-90 i 90-10. To są moje wyniki, pierwsza i ostatnia pętla są w większości takie same, ale druga jest znacznie szybsza, szczególnie w przypadku 10-90. Dlaczego dokładnie? Zawsze uważałem, że Lambda ma dobrą wydajność.

EDIT

count++ w rzeczywistości nie jest to, co wewnątrz pętli, po prostu dodać, że tutaj w celach demonstracyjnych, chyba powinien Użyłem „// zrób coś tutaj”

Performance Results

EDIT 2

Wyniki systemem każdy jeden tysiąc razy: Performance Results 1000 times

+2

Byłoby interesujące zobaczyć, jak 'List.Where (x =>! X.Value.Equals (" Nie recenzja ")). Count()' wykonuje w porównaniu do tych. –

+11

@MikePrecup: A jeszcze lepiej, 'List.Count (x =>! X.Value.Equals (" Nie zweryfikowany "))' –

+1

Czy upewniłeś się, że nie popełniłeś żadnego z tych błędów [Benchmarków wydajności] (http : //tech.pro/blog/1293/c-performance-benchmark-mistakes-part-one)? – Corak

Odpowiedz

9

Zasadniczo istnieje niewielka ilość dodatkowego zadnie - zarówno w badaniu poprzez delegata, a dla części iteracji. Biorąc pod uwagę, jak niewiele pracy wykonuje się w tej iteracji, ten dodatkowy kierunek jest relatywnie drogi.

To nie jest ani zaskakujące, ani niepokojące, według mnie. Jest to rodzaj mikro-optymalizacji, którą możesz łatwo wykonać, jeśli jesteś w rzadkiej sytuacji, gdy jest ona istotna w twojej aplikacji w świecie rzeczywistym. Z mojego doświadczenia wynika, że ​​rzadko spotykane w tej pętli jest wąskie gardło w aplikacji.Normalne podejście powinno być:

  • określenia wymagań wydajności
  • wdrożenia wymagań funkcjonalnych w najczystszej, najprostszej drodze można
  • Zmierz swoje wyniki w stosunku do wymagań
  • Jeśli wydajność znajduje chcąc, zbadać dlaczego i tylko odejdź od jasności tak mało jak to tylko możliwe, otrzymując największy "huk za złotówki", który możesz
  • Powtarzaj, aż skończysz:

Odpowiadając na EDIT:

Ilość ++ nie jest rzeczywiście to, co jest w środku pętli, po prostu dodać, że tutaj w celach demonstracyjnych, chyba powinien Użyłem „// zrób coś tutaj”

Cóż, to jest najważniejsze - im więcej pracy zostanie wykonane, tym mniej znaczące będą cokolwiek innego. Po prostu liczenie jest cholernie szybkie, więc spodziewam się dużej rozbieżności. Wykonuj dowolną ilość prawdziwej pracy, a różnica będzie mniejsza.