Ez a cikk egy tükör gépi fordítás, kérjük, kattintson ide, hogy ugorjon az eredeti cikkre.

Nézet: 6317|Válasz: 3

[Forrás] [Fordulás]. NET teljesítményoptimalizálások – gyors áthaladás a lista gyűjteményein

[Linket másol]
Közzétéve: 2022-8-28 20:51:16 | | | |
Rövid bevezetés

A System.Collections.Generic.List <T>egy általános gyűjtési osztály a .NET nyelven, amely bármilyen adattípust képes tárolni kényelme és gazdag API-ja miatt, amelyet széles körben használnak a mindennapi életünkben, és nevezhetjük a leggyakrabban használt gyűjteményosztálynak.

A kódírásban gyakran át kell futtatnunk egy <T>Lista gyűjteményt, hogy megszerezzük az elemeket üzleti feldolgozáshoz. Általában nincs sok elem egy készletben, és nagyon gyorsan áthaladhat. De néhány nagy adatfeldolgozás, statisztika, valós idejű számítástechnika <T>stb. esetén hogyan lehet gyorsan áthaladni a tízezrek vagy százezrek adatgyűjtésén? Ezt kell ma megosztanom veled.

Áthaladási mód

Nézzük meg a különböző áthaladási módszerek teljesítményét, és építsük fel a következő teljesítménymérföldet, különböző nagyságrendű gyűjtési áthaladást használva, hogy megtekintsük a különböző módszerek teljesítményét. A kódrészlet így néz ki:

Használd a foreach utasítást

Foreach a leggyakoribb módja a gyűjtemények áthaladásának, ez egy szintaxis-cukor megvalósítása az iterátor mintának, és emiatt is mérföldkőként használják.

Mivel a foreach utasítás szintaxiscukor, a fordító végül a GetEnumerator() és a MoveNext() kódokat hívja egy while hurokkal a funkció megvalósításához. A fordított kód így néz ki:



A MoveNext() metódus megvalósítása biztosítja, hogy ne módosítsák a gyűjteményt az iterációban, és ha a módosítás bekövetkezik, akkor InvalidOperationException kivételt ad ki, és túlcsordulást végez, hogy ellenőrizze, a jelenlegi index hiteles-e, valamint a megfelelő elemet is hozzá kell rendelnie az enumerátorhoz. Jelenlegi attribútum,Szóval valójában a teljesítménye nem a legjobb, a kód részlet így néz ki:



Nézzük meg, hogyan teljesít különböző készletméretekben, és az eredmények így néznek ki:



Látható, hogy különböző méreteknél a lineáris növekedési kapcsolat szükséges az időigényes folyamatban, még akkor is, ha 100w adatot halad át folyamatos logika nélkül, legalább 1 másodpercet igényel.

Használd a ForEach listázás módszerét

Egy másik gyakori mód a <T>Lista használata. ForEach() módszer, amely lehetővé teszi, hogy egy Akció delegált adj át, <T>aki az Akció delegált hívja, miközben az iterált az <T>elemen.

Ez a <T>Lista belső megvalósítási módszere, így közvetlenül hozzáférhet privát tömbökhöz, és elkerülheti a túlcsordulásokat. Elméletileg gyorsnak kellene lennie; De a mi helyzetünkben csak egy üres metódus van, amely nem feltétlenül viselkedik jól egy teljesen inline hívással a foreach metódásra. Az alábbiakban a ForEach metódus forráskódja látható, amely azt mutatja, hogy nincs túlcsordulás ellenőrzése, de továbbra is megtartja a párhuzamos verziószám-ellenőrzést.



Ezen túlmenően, mivel a hívó kódban szükség van delegált objektumot továbbítani a ForEach metódusnak, az ellenőrzi majd, hogy a zárás generáló osztály delegált objektuma mindig üres-e, ha nem, akkor az új Akció<T>(), ahogy az alábbiakban látható:



Nézzük meg, hogyan viszonyul a foreach kulcsszóhoz teljesítmény szempontjából. Az alábbi kép mutatja a benchmark eredményeit:



A teszteredmények alapján 40%-kal lassabb, mint közvetlenül a foreach kulcsszó használata, úgy tűnik, ha nem szükséges, akkor jobb választás közvetlenül foreach használni, szóval van gyorsabb megoldás?

Hurokvándorláshoz

Visszatérve a legrégebbi módszerünkhöz, vagyis a for kulcsszót használjuk a gyűjtemény bejárásához. Ez lehet a legjobban teljesítő átjárási módszer jelenleg is, mert nem igényel olyan redundáns kódot, mint az előzők (bár az indexer is ellenőrizve van a túlcsordulás megelőzése érdekében), és nyilván nem nézi meg a verziószámot, így többszálas környezetben a gyűjtemény változik, és nem kerül kivétel for használatkor. A tesztkód így néz ki:

Nézzük, hogyan alakul.



Úgy tűnik, ez az, ahogy várjuk.A for hurok közvetlen használata 60%-kal gyorsabb, mint az foreach, egy olyan készlet, amely korábban 1 másodpercig tartott a forgatáshoz, most már csak 400 milliszekundumot vesz igénybe. Szóval van gyorsabb megoldás?

Gyűjtemények használataMarshal

A .NET5 után a dotnet közösség bevezette a CollectionsMarshal osztályt a gyűjteményműveletek teljesítményének javítása érdekében. Ez az osztály megvalósítja, hogyan lehet natív tömbökhöz hozzáférni a gyűjteménytípusok (ha láttad az én [. .NET teljesítményoptimalizálás – be kell állítanod a gyűjteménytípusok kezdeti méretét] cikkben, tudod, hogy sok adatstruktúra mögött lévő megvalósítás a tömbök. Így kihagyhat mindenféle észlelést, és közvetlenül hozzáférhet az eredeti tömbhöz, ami a leggyorsabbnak kellene lennie. A kód így néz ki:

Láthatod, hogy a fordító által generált kód nagyon hatékony.



Közvetlen hozzáférés az alapul szolgáló tömbhöz nagyon veszélyes, tudnod kell, mit csinálsz minden kódsorral, és kell elég tesztelésre lenne szükséged. A benchmark eredmények a következők:



A CollectionsMarshal használata 79%-kal gyorsabb, mint a foreach használata, de ennek kell lennie a JIT optimalizálásának oka is, nincs nagy különbség a foreach és a for for kulcsszó loop Span használata között.

összefoglalás

Ma arról beszéltem, hogyan lehet gyorsan áthaladni a Lista gyűjteményben, és a legtöbb esetben ajánlott a foreach kulcsszó használatát, amely egyszerre tartalmaz túlcsordulást és többszálas verziószám-vezérlést, ami megkönnyíti a megfelelő kód megírását.

Ha nagy teljesítményre és nagy adatmennyiségre van szükséged, ajánlott közvetlenül a CollectionsMarshal.AsSpan használatát a gyűjtemény átjárásához.

A cikk forráskód linkje:

A hiperlink bejelentkezés látható.

Eredeti link:A hiperlink bejelentkezés látható.





Előző:A RabbitMQ AMQP üzenetarchitektúrájának részletes magyarázata
Következő:Hálózati kábel kristályfej T568A és T568B szabvány és különbség
Közzétéve: 2022-9-4 22:15:52 |
Tanulj meg
Közzétéve: 2022-9-8, 10:33:05 |
Tanulj meg
Közzétéve: 2023-6-27 22:39:13 |
Halló 12306 Tudna privát üzenetet küldeni adatokkal
Lemondás:
A Code Farmer Network által közzétett összes szoftver, programozási anyag vagy cikk kizárólag tanulási és kutatási célokra szolgál; A fenti tartalmat nem szabad kereskedelmi vagy illegális célokra használni, különben a felhasználók viselik az összes következményet. Az oldalon található információk az internetről származnak, és a szerzői jogi vitáknak semmi köze ehhez az oldalhoz. A fenti tartalmat a letöltés után 24 órán belül teljesen törölni kell a számítógépéről. Ha tetszik a program, kérjük, támogassa a valódi szoftvert, vásároljon regisztrációt, és szerezzen jobb hiteles szolgáltatásokat. Ha bármilyen jogsértés történik, kérjük, vegye fel velünk a kapcsolatot e-mailben.

Mail To:help@itsvse.com