Linq – optymalizacja Single oraz Last

Ostatnimi czasy zamiast siedzieć nad moim gitWebem, grzebie w kodzie źródłowym .NET. W dzisiejszym wpisie chciałem opisać dwie bardzo przydatne oraz często wykorzystywane metody LinqSingle oraz Last.

Ale dlaczego opisywać tak proste i powszechnie wykorzystywane metody?

Ano dlatego:

Single

Widzicie?  Warunek jest weryfikowany na każdym elemencie kolekcji. Pytanie brzmi dlaczego na każdym?! Czy sprawdzanie nie powinno być przerwane na drugim elemencie spełniającym warunek? Moja implementacja pętli:

To teraz benchmark:

Jak widać wyniki mówią same za siebie.

Ciekawa implementacja znajduje się w CoreFx. Sprytnie zlikwidowano zamieniono zliczanie powtórzeń i warunek sprawdzający na dodatkową wewnętrzną pętlę, iterującą od momentu spełnienia warunku.

 

Pierwsze wzmianki nt. tego błędu/niedoskonałości można znaleźć już w 2013 roku, póki co w obecnej wersji .NET nie zostało to jeszcze poprawione. Jak dobrze zauważył kolega Szymon brak poprawy w implementacji mógł być spowodowany koniecznością zachowania wstecznej kompatybilności. Ale dalej uważam, że stosowne by było dodanie chociaż w komentarzu wzmianki.

Last

Obecna implementacja:

Jaki tu jest problem? Metoda Last, która ma pobrać ostatni pasujący element iteruje od początku! W przypadku list gdzie mamy dostęp do elementu poprzez indeks, aż się prosi aby iterować od tyłu. Lepsza wersja mogła by wyglądać tak:

 

Tak jak w metodzie Single, trudno mi zrozumieć, dlaczego to jeszcze nie zostało naprawione. Wydaje się, że było to najwidoczniej przeoczenie bo w implementacji .NET Core obie dwie metody zostały poprawione (last, single)

Podsumowanie

Mam nadzieje, że po przeczytaniu tego posta nie zaczniecie przepisywać Waszych aplikacji na nowo. Nie o to chodzi. Prawdopodobnie w 99% przypadków ten błąd nie będzie miał większego znaczenia na działanie Waszej aplikacji. Ważne jest to aby widzieć, że coś takiego występuje.

Po raz kolejny chciałem pokazać, że wiedza o narzędziach/bibliotekach jest szalenie istotna. Może w tej aplikacji nie będzie Ci potrzebna optymalizacja na tym poziome, no ale w następnej?

Ps. Pisząc tego posta szukałem materiałów i natrafiłem na post Jona na ten sam temat.