"Zagnieżdżone foreach "vs" lambda/LINQ query " performance (LINQ-to-Objects) [closed]
chcesz poprawić to pytanie? Update the question so it edytując ten post.
Zamknięte 4 lata temu .
Popraw to pytanieW performance point of view co należy użyć" zagnieżdżonych zapytań foreach ' s "lub" lambda/linq queries"?
5 answers
Napisz najczystszy kod, jaki możesz, a następnie porównaj i profiluj, aby odkryć wszelkie problemy z wydajnością. Jeśli masz problemy z wydajnością, możesz poeksperymentować z innym kodem, aby dowiedzieć się, czy jest szybszy, czy nie (mierzenie przez cały czas z jak najbardziej realistycznymi danymi), a następnie dokonać oceny, czy poprawa wydajności jest warta trafienia czytelności.
Bezpośrednie podejście foreach
będzie szybsze niż LINQ w wielu przypadkach. Na przykład, rozważmy:
var query = from element in list
where element.X > 2
where element.Y < 2
select element.X + element.Y;
foreach (var value in query)
{
Console.WriteLine(value);
}
Teraz są dwie klauzule where
i klauzula select
, więc każdy ewentualny element musi przejść przez trzy Iteratory. (Oczywiście dwa, gdzie klauzule mogą być połączone w tym przypadku, ale robię ogólną uwagę.)
Teraz porównaj go z kodem bezpośrednim:
foreach (var element in list)
{
if (element.X > 2 && element.Y < 2)
{
Console.WriteLine(element.X + element.Y);
}
}
To będzie działać szybciej, ponieważ ma mniej obręczy do przejechania. Są szanse, że wyjście konsoli zmniejszy koszt iteratora, a ja na pewno wolę LINQ zapytanie.
EDIT: odpowiedź na temat zagnieżdżonych pętli foreach... zazwyczaj są one reprezentowane przez SelectMany
lub drugą from
klauzulę:
var query = from item in firstSequence
from nestedItem in item.NestedItems
select item.BaseCount + nestedItem.NestedCount;
Tutaj dodajemy tylko jeden dodatkowy iterator, ponieważ będziemy już używać dodatkowego iteratora na element w pierwszej sekwencji ze względu na zagnieżdżoną pętlę foreach
. Jest jeszcze trochę narzutu, w tym narzutu z robienia projekcji w delegacie zamiast " inline "(o czym wcześniej nie wspomniałem), ale nadal nie będzie bardzo różnie do wykonania zagnieżdżonego-foreach.
To nie znaczy, że nie możesz strzelić sobie w stopę LINQ, oczywiście. Możesz pisać zdumiewająco nieefektywne zapytania, jeśli nie zaangażujesz najpierw swojego mózgu - ale to nie jest unikalne dla LINQ...
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-25 14:42:25
If you do
foreach(Customer c in Customer)
{
foreach(Order o in Orders)
{
//do something with c and o
}
}
Wykonasz klienta.Count * Order.Liczba iteracji
If you do
var query =
from c in Customer
join o in Orders on c.CustomerID equals o.CustomerID
select new {c, o}
foreach(var x in query)
{
//do something with x.c and x.o
}
Wykonasz klienta.Licznik + Kolejność.Policz iteracje, bo Wylicz.Join jest zaimplementowany jako HashJoin.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-25 14:31:09
To bardziej skomplikowane. Ostatecznie, wiele z LINQ-to-Objects jest (za kulisami) pętlą foreach
, ale z dodanym nadmiarem trochę abstrakcji / bloków iteratora / itp. Jednak, o ile nie zrobisz zupełnie różnych rzeczy w swoich dwóch wersjach (foreach vs LINQ), obie powinny być O (N).
Prawdziwe pytanie brzmi: czy istnieje lepszy sposób napisania twojego specyficznego algorytmu , który oznacza, że foreach
byłby nieefektywny? Czy LINQ może to zrobić za Ciebie?
Na przykład LINQ ułatwia hashowanie / grupowanie / sortowanie danych.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-25 14:29:01
To już zostało powiedziane, ale zasługuje na powtórzenie.
Programiści nigdy nie wiedzą, gdzie jest wąskie gardło wydajności, dopóki nie przeprowadzą testów wydajności.
To samo dotyczy porównania techniki A do techniki B. Jeśli nie ma dramatycznej różnicy, musisz ją po prostu przetestować. Może to być oczywiste, jeśli masz scenariusz O(n) vs O(N^x), ale ponieważ LINQ jest głównie kompilatorem, zasługuje na profilowanie.
Poza tym, chyba że twój projekt jest w produkcji i sprofilowałeś kod i stwierdziłeś, że ta pętla spowalnia Twoje wykonanie, pozostaw ją jako preferowaną czytelność i konserwację. Przedwczesna optymalizacja to diabeł.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-25 14:43:23
Wielką zaletą jest to, że korzystanie z zapytań Linq-to-Objects daje możliwość łatwego przekazania zapytania do PLinq, a system automatycznie wykona operację na odpowiedniej liczbie wątków dla bieżącego systemu.
Jeśli używasz tej techniki na dużych zestawach danych, to łatwo stać się wielką wygraną dla bardzo małych problemów.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-25 14:44:00