Tento článok je zrkadlovým článkom o strojovom preklade, kliknite sem pre prechod na pôvodný článok.

Pohľad: 6317|Odpoveď: 3

[Zdroj] [Otoč]. Optimalizácie výkonu NET – rýchle prechádzanie zoznamových kolekcií

[Kopírovať odkaz]
Zverejnené 2022-8-28 20:51:16 | | | |
Stručný úvod

System.Collections.Generic.List <T>je všeobecná trieda kolekcií v .NET, ktorá dokáže ukladať akýkoľvek typ dát vďaka svojmu pohodliu a bohatému API, ktoré je široko používané v každodennom živote a možno ho označiť za najpoužívanejšiu triedu kolekcií.

Pri písaní kódu často potrebujeme prechádzať kolekciou zoznamov, <T>aby sme získali prvky v nej pre niektoré obchodné spracovania. Normálne nie je v množstve veľa prvkov a je veľmi rýchle prechádzanie. Ale pri spracovaní veľkých dát, štatistike, výpočtoch v reálnom čase a podobne<T>, ako rýchlo prechádzať zoznamom desiatok tisíc alebo stoviek tisíc dát? To je to, čo vám dnes potrebujem povedať.

Prechodový režim

Pozrime sa na výkon rôznych metód prechádzania a vytvorme nasledujúci výkonnostný benchmark, pričom použijeme rôzne rády triedy zberu na sledovanie výkonu rôznych metód. Úryvok kódu vyzerá takto:

Použite príkaz foreach

Foreach je najbežnejší spôsob, akým prechádzame kolekcie, ide o syntax sugar implementáciu iterátorového vzoru a používa sa aj ako referenčný bod pre toto obdobie.

Keďže príkaz foreach je syntaktický cukor, kompilátor nakoniec volá GetEnumerator() a MoveNext() pomocou while slučky na implementáciu funkcionality. Skompilovaný kód vyzerá takto:



Implementácia metódy MoveNext() zabezpečí, že v iterácii nebudú žiadne ďalšie vlákna upravovať kolekciu, a ak k úprave dôjde, vyhodí výnimku InvalidOperationException a vykoná overflow check, aby overila, či je aktuálny index legitímny, a tiež musí priradiť príslušný prvok enumerátorovi. Súčasný atribút,Takže v skutočnosti jeho výkon nie je najlepší, úryvok kódu vyzerá takto:



Pozrime sa, ako funguje naprieč rôznymi veľkosťami množín, a výsledky vyzerajú takto:



Je vidieť, že pri rôznych veľkostiach je potrebný lineárny rastový vzťah časovo náročného procesu, aj keď prechádza 100 W dát bez akejkoľvek logiky spracovania, trvá to aspoň 1 sekundu.

Použite metódu zoznamu ForEach

Ďalším bežným spôsobom je používať List<T>. Metóda ForEach(), ktorá vám umožní zadať <T>delegáta akcie, ktorý bude volať delegáta akcie počas jeho iterácie cez <T>prvok.

Je to <T>interná implementačná metóda Listu, takže môže priamo pristupovať k súkromným poliam a vyhnúť sa kontrole pretečenia. V teórii by to malo byť rýchle; Ale v našom prípade existuje len jedna prázdna metóda, ktorá sa nemusí správať dobre pri plne inline volaní foreach metódy. Nižšie je zdrojový kód metódy ForEevery (Zdroj), ktorý ukazuje, že nemá overflow checking, ale stále zachováva súčasné overovanie čísla verzie.



Okrem toho, keďže je potrebné odovzdať delegáta metóde ForEevery v volacom kóde, bude kontrolovať, či je objekt delegátu v triede generovania uzavretia zakaždým prázdny, a ak nie, nový Action<T>(), ako je uvedené nižšie:



Pozrime sa, ako sa porovnáva s kľúčovým slovom foreach z hľadiska výkonu. Nasledujúci obrázok ukazuje výsledky benchmarku:



Podľa výsledkov testu je to o 40 % pomalšie ako priame použitie kľúčového slova foreach, zdá sa, že ak to nie je nevyhnutné, je lepšie použiť foreach priamo, takže existuje nejaký rýchlejší spôsob?

pre prechod slučkou

Vracajúc sa k nášmu najstaršiemu spôsobu, ktorým je používať kľúčové slovo for na prechádzanie kolekciou. Momentálne by to mala byť najvýkonnejšia metóda prechádzania, pretože nevyžaduje nejaký redundantný kód ako predchádzajúce (hoci indexer je tiež kontrolovaný, aby sa zabránilo pretečeniu), a samozrejme nekontroluje číslo verzie, takže v multithreaded prostredí sa kolekcia mení a pri použití pre nebude vyhodená žiadna výnimka. Testovací kód vyzerá takto:

Uvidíme, ako to dopadne.



Zdá sa, že takto to očakávame.Použitie priamo for-loopu je o 60 % rýchlejšie ako foreachsada, ktorá kedysi trvala 1 sekundu na prechod, teraz trvá len 400 milisekúnd. Existuje teda rýchlejší spôsob?

Využitie zbierokMaršal

Po .NET5 komunita dotnet implementovala triedu CollectionsMarshal, aby zlepšila výkon operácií zbierky. Táto trieda implementuje, ako pristupovať k natívnym poliam typov kolekcií (ak ste videli môj [. .NET Performance Optimization – mali by ste nastaviť počiatočnú veľkosť pre typy kolekcií, viete, že základnou implementáciou mnohých dátových štruktúr sú polia). Takže dokáže preskočiť všetky druhy detekcií a priamo pristupovať k pôvodnému poľu, ktoré by malo byť najrýchlejšie. Kód vyzerá takto:

Vidíte, že kód generovaný kompilátorom je veľmi efektívny.



Priamy prístup k podkladovému poľu je veľmi nebezpečný, musíte vedieť, čo robíte s každým riadkom kódu, a mať dostatočné testovanie. Výsledky benchmarku sú nasledovné:



WowPoužívanie CollectionsMarshal je o 79 % rýchlejšie ako použitie foreach, ale malo by to byť dôvodom optimalizácie JIT, nie je veľký rozdiel medzi používaním foreach a pre kľúčové slovo loop Span.

súhrn

Dnes som s vami hovoril o tom, ako rýchlo prechádzať kolekciou List, a vo väčšine prípadov sa odporúča použiť kľúčové slovo foreach, ktoré má overflow checking aj viacvláknovú kontrolu verziových čísel, čo nám môže uľahčiť písanie správneho kódu.

Ak potrebujete vysoký výkon a veľké objemy dát, odporúča sa použiť pre a CollectionsMarshal.AsSpan priamo na prechádzanie kolekciou.

Odkaz na zdrojový kód tohto článku:

Prihlásenie na hypertextový odkaz je viditeľné.

Pôvodný odkaz:Prihlásenie na hypertextový odkaz je viditeľné.





Predchádzajúci:Podrobné vysvetlenie architektúry správ RabbitMQ AMQP
Budúci:Štandard a rozdiel medzi sieťovými kryštálovými hlavami T568A a T568B
Zverejnené 4.9.2022 22:15:52 |
Naučte sa učiť
Zverejnené 8.9.2022 10:33:05 |
Naučte sa učiť
Zverejnené 27. 6. 2023 22:39:13 |
Dobrý deň, 12306. Môžete mi poslať súkromnú správu s dátami?
Vyhlásenie:
Všetok softvér, programovacie materiály alebo články publikované spoločnosťou Code Farmer Network slúžia len na vzdelávacie a výskumné účely; Vyššie uvedený obsah nesmie byť použitý na komerčné alebo nezákonné účely, inak nesú všetky následky používateľmi. Informácie na tejto stránke pochádzajú z internetu a spory o autorské práva s touto stránkou nesúvisia. Musíte úplne vymazať vyššie uvedený obsah zo svojho počítača do 24 hodín od stiahnutia. Ak sa vám program páči, podporte originálny softvér, zakúpte si registráciu a získajte lepšie originálne služby. Ak dôjde k akémukoľvek porušeniu, kontaktujte nás prosím e-mailom.

Mail To:help@itsvse.com