Ten artykuł jest lustrzanym artykułem tłumaczenia maszynowego, kliknij tutaj, aby przejść do oryginalnego artykułu.

Widok: 6317|Odpowiedź: 3

[Źródło] [Skręć]. Optymalizacje wydajności NET – szybkie przeszukiwanie kolekcji List

[Skopiuj link]
Opublikowano 2022-8-28 20:51:16 | | | |
Krótkie wprowadzenie

System.Collections.Generic.List <T>to klasa zbiorów ogólnych w .NET, która może przechowywać dowolny typ danych dzięki wygodzie i bogatemu API, szeroko używanej w naszym codziennym życiu i można ją uznać za najczęściej używaną klasę kolekcji.

W pisaniu kodu często musimy iterować <T>przez kolekcję List, aby uzyskać elementy z niej do niektórych procesów biznesowych. Zazwyczaj w zestawie nie ma wielu elementów i bardzo szybko się po nim porusza. Ale w przypadku przetwarzania big data, statystyki, obliczeń w czasie rzeczywistym itd<T>., jak szybko przeszukać kolekcję dziesiątek lub setek tysięcy danych z list? To właśnie muszę dziś z wami powiedzieć.

Tryb przejścia

Przyjrzyjmy się wydajności różnych metod przechodzenia i zbudujmy następujący benchmark wydajności, wykorzystując różne rządy wielkości przejścia kolekcji, aby sprawdzić wydajność różnych metod. Fragment kodu wygląda tak:

Użyj instrukcji foreach

Foreach jest najczęstszym sposobem przeglądania kolekcji, jest to implementacja wzorca iteratora w formacji cukru składniowego i służy także jako punkt odniesienia dla tego czasu.

Ponieważ instrukcja foreach jest składnią cukru, kompilator ostatecznie wywołuje GetEnumerator() i MoveNext() za pomocą pętli while, aby zaimplementować tę funkcjonalność. Skompilowany kod wygląda tak:



Implementacja metody MoveNext() zapewni, że nie będzie innych wątków modyfikujących kolekcję w iteracji, a jeśli modyfikacja nastąpi, wygeneruje wyjątek InvalidOperationException oraz sprawdzi overflow check, aby sprawdzić, czy aktualny indeks jest legalny, a także musi przypisać odpowiadający element do popisowanego. Obecna cecha,W rzeczywistości jego wydajność nie jest najlepsza, fragment kodu wygląda tak:



Przyjrzyjmy się, jak działa na różnych rozmiarach zestawów, a wyniki wyglądają tak:



Widać, że w przypadku różnych rozmiarów wymagana jest liniowa zależność wzrostu czasochłonnego procesu, nawet jeśli przechodzi on 100W danych bez logiki przetwarzania, zajmuje to co najmniej 1 sekundę.

Użyj metody ForEach List

Innym popularnym sposobem jest użycie <T>Listy. Metoda ForEach(), która pozwala przekazać <T>delegata Akcji, który wywołuje delegata Akcji podczas iteracji przez element<T>.

Jest to <T>wewnętrzna metoda implementacji List, dzięki czemu może bezpośrednio uzyskać dostęp do prywatnych tablic i uniknąć kontroli przepełnienia. Teoretycznie powinno być szybko; Ale w naszym przypadku jest tylko jedna pusta metoda, która może nie działać dobrze przy pełnym wywołaniu inline do metody foreach. Poniżej znajduje się kod źródłowy metody ForEEvery (AEEE), który pokazuje, że nie posiada sprawdzania przebiegu, ale nadal zachowuje jednoczesne sprawdzanie numerów wersji.



Dodatkowo, ponieważ konieczne jest przekazanie delegata do metody ForEEvery w kodzie wywoławczym, będzie ona sprawdzać, czy obiekt delegata w klasie generowania zamknięcia jest za każdym razem pusty, a jeśli nie, to nowy Action<T>(), jak pokazano poniżej:



Przyjrzyjmy się, jak wypada to w porównaniu ze słowem kluczowym foreach pod względem wydajności. Poniższy obraz przedstawia wyniki testu referencyjnego:



Sądząc po wynikach testów, jest o 40% wolniejszy niż bezpośrednie użycie słowa kluczowego foreach, wydaje się, że jeśli nie jest konieczne, lepiej jest użyć foreach bezpośrednio, więc czy jest jakiś szybszy sposób?

dla przechodzenia pętli

Wracając do naszego najstarszego sposobu, czyli używania słowa klucza for do przemieszczania się po kolekcji. Powinna to być obecnie najlepiej działająca metoda przeszukiwania, ponieważ nie wymaga jakiegoś redundantnego kodu jak poprzednie (choć indekser jest też sprawdzany, by zapobiec przepełnieniom), a oczywiście nie sprawdza numeru wersji, więc w środowisku wielowątkowym kolekcja jest zmieniana i nie będzie wyjątku przy użyciu for. Kod testowy wygląda tak:

Zobaczymy, jak to wyjdzie.



Wygląda na to, że tak się tego spodziewamy.Bezpośrednie użycie pętli for jest o 60% szybsze niż foreach, zestaw, który kiedyś zajmował 1 sekundę, teraz zajmuje tylko 400 milisekund. Czy jest szybszy sposób?

Użycie Kolekcji Marszałek

Po .NET5 społeczność dotnet wdrożyła klasę CollectionsMarshal, aby poprawić wydajność operacji kolekcji. Ten kurs implementuje dostęp do natywnych tablic typów kolekcji (jeśli widziałeś mój [. .NET Performance Optimization – powinieneś ustawić początkowy rozmiar dla typów kolekcji, wiesz, że podstawową implementacją wielu struktur danych są tablice). Dzięki temu może pominąć różne detekcje i bezpośrednio uzyskać dostęp do oryginalnej tablicy, która powinna być najszybsza. Kod wygląda tak:

Widać, że kod generowany przez kompilator jest bardzo wydajny.



Bezpośredni dostęp do bazowej macierzy jest bardzo niebezpieczny, musisz wiedzieć, co robisz z każdą linijką kodu i mieć wystarczająco dużo testów. Wyniki benchmarku przedstawiają się następująco:



WowKorzystanie z CollectionsMarshal jest o 79% szybsze niż foreach, ale to powinien być powód optymalizacji JIT, nie ma dużej różnicy między użyciem foreach a for keyword loop Span.

streszczenie

Dziś rozmawiałem z Wami o tym, jak szybko przechodzić przez kolekcję List, a w większości przypadków zaleca się używanie słowa kluczowego foreach, które posiada zarówno overflow checking, jak i wielowątkową kontrolę numerów wersji, co ułatwia nam pisanie poprawnego kodu.

Jeśli potrzebujesz wysokiej wydajności i dużych ilości danych, zaleca się bezpośrednie korzystanie z for and CollectionsMarshal.AsSpan do przeglądania kolekcji.

Link do kodu źródłowego tego artykułu:

Logowanie do linku jest widoczne.

Oryginalny link:Logowanie do linku jest widoczne.





Poprzedni:Szczegółowe wyjaśnienie architektury wiadomości AMQP w RabbitMQ
Następny:Główne głowice kryształowe sieci T568A i T568B i różnice
Opublikowano 2022-9-4 22:15:52 |
Naucz się uczyć
Opublikowano 2022-9-8 10:33:05 |
Naucz się uczyć
Opublikowano 2023-6-27 22:39:13 |
Halo 12306. Czy możesz wysłać mi prywatną wiadomość z danymi?
Zrzeczenie się:
Całe oprogramowanie, materiały programistyczne lub artykuły publikowane przez Code Farmer Network służą wyłącznie celom edukacyjnym i badawczym; Powyższe treści nie mogą być wykorzystywane do celów komercyjnych ani nielegalnych, w przeciwnym razie użytkownicy ponoszą wszelkie konsekwencje. Informacje na tej stronie pochodzą z Internetu, a spory dotyczące praw autorskich nie mają z nią nic wspólnego. Musisz całkowicie usunąć powyższą zawartość z komputera w ciągu 24 godzin od pobrania. Jeśli spodoba Ci się program, wspieraj oryginalne oprogramowanie, kup rejestrację i korzystaj z lepszych, autentycznych usług. W przypadku naruszenia praw prosimy o kontakt mailowy.

Mail To:help@itsvse.com