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

Nézet: 6846|Válasz: 2

[Forrás] [Fordulás]. .NET teljesítményoptimalizálás - Collections.Pooled ajánlott

[Linket másol]
Közzétéve: 2022-5-29 13:45:22 | | | |
Rövid bevezetés

A teljesítményoptimalizálás azt jelenti, hogy ugyanannyi kérés feldolgozása kerüljön kevesebb erőforrással, amelyek általában CPU-val vagy memóriával rendelkeznek, és természetesen az operációs rendszer IO-kezelései, hálózati forgalom, lemezhasználat stb. De legtöbbször csökkentjük a CPU és a memória használatát.
A korábban megosztott tartalomnak vannak korlátai, nehéz közvetlenül átalakítani, ma egy egyszerű módszert szeretnék megosztani veled, csak néhány gyűjteménytípust kell kicserélni, hogy javítsd a teljesítményt és csökkentsd a memória igényét.
Ma szeretném megosztani veletek egy osztálykönyvtárat, eztAz osztálykönyvtár neve Collections.PooledAhogy a névből is látszik, a csoportos memórián keresztül történik a memória és a GC csökkentése érdekében, és közvetlenül megnézzük, milyen teljesítmény, valamint elviszünk a forráskódot is, hogy miért hozza ezeket a teljesítményjavulásokat.

Gyűjtemények. Összegyűjtött

Projekt linkje:A hiperlink bejelentkezés látható.

A könyvtár a System.Collections.Generic osztályokon alapul, amelyeket módosítottak, hogy kihasználják az új System.Span <T>és System.Buffers.ArrayPool <T>osztálykönyvtárakat a memória leosztásának, a teljesítmény javításának és a modern API-kkal való nagyobb interoperabilitásnak való lehetővé tétele érdekében.
A Collections.Pooled támogatja a .NET Standnd 2.0-t (.NET Framework 4.6.1+), valamint támogatja a . NET Core 2.1+. A CoreFX-ről kiterjedt egységtesztek és benchmarkok kerültek át.

A tesztek összesített száma: 27501. Via: 27501. Kudarc: 0. Skip: 0.
A próbafutás sikeres volt.
Teszt végrehajtási ideje: 9,9019 másodperc

Hogyan kell használni

Ezt a könyvtárat könnyen telepítheted Nuget vagy NuGet verzióval is.

A Collections.Pooled könyvtárban a leggyakrabban használt gyűjteménytípusok csoportos verzióit valósítja meg, ahogy azt a .NET natív típusokkal való összehasonlítás is mutatja.

. .NET natívGyűjtemények. Összegyűjtöttmegjegyzés
Lista<T>PooledList<T>Általános gyűjteményosztályok
Szótár<TKey, TValue>PooledDictionary<TKey, TValue>Általános szótárosztály
HashSet<T>PooledSet<T>Általános hash gyűjtemény osztályok
Boglya<T>Boglya<T>Általános vermek
Sor<T>PooledQueue<T>Általános kohorsz

Használatkor csak a hozzá tartozó . .NET natív verzió a Collections.Pooled verzióval, ahogy az alábbi kódban látható:

Ugyanakkor meg kell jegyeznünk, hogy a Pooled típus az IDispose interfészt valósítja meg, amely a használt memóriát a Dispose() metódóval visszaadja a poolba, ezért a Pooled gyűjtemény objektum használata után hívjuk a Dispose() metódust. Vagy közvetlenül a var használó kulcsszót használhatod.

Megjegyzés: Használd a gyűjtemény objektumot a Collections.Pooled területénA legjobb, ha kézzel kell kiadni, de nem számít, ha nem engeded ki, a GC végül újrahasznosítja, de nem lehet visszaállítani a poolba, és nem éri el a memória megtakarításának hatását.
Mivel újrahasznosítja a memóriateret, amikor visszaadja a memória térét a poolba, fel kell dolgoznia a gyűjtemény elemeit, és egy ClearMode nevű felsorolást biztosít, amely a következőképpen definiálható:




Alapértelmezés szerint az alapértelmezett Auto értéket használhatod, és ha speciális teljesítménykövetelmények vannak, akkor a kockázatok ismerete után használhatod a Neso-t.
Referenciatípusok és értéktípusok esetén, amelyek hivatkozási típusokat tartalmaznak, a tömbhivatkozást ki kell ürítenünk, amikor visszaadjuk a memória téret a poolba; ha nem tisztítják meg, a GC nem tudja felszabadítani ezt a memória részt (mert az elem hivatkozása mindig is a pool volt), ha tiszta értéktípus, akkor nem lehet kiüríteni; ebben a cikkben leírom a tároló különbséget a referenciatípusok és struktur (értéktípus) tömbök között, a tiszta értéktípusoknak nincs objektumfejléc-újrahasznosítása, és nem igényelnek GC beavatkozást.


. .NET teljesítményoptimalizálás – Használj struct alternatív osztályokat:A hiperlink bejelentkezés látható.

Teljesítményösszehasonlítás

Nem csináltam egyedül a Benchmarkot, és a nyílt forráskódú projektek futó pontszáma 0 volt sok projekt memóriahasználatában, mert a használt memóriának nem volt plusz lefoglalása.

PooledList<T>

Körbefutni a Benchmark-ban hozzáadott 2048 elemeket a készlethez. A .NET natív <T>listához 110us (a tényleges benchmark eredmények szerint az ábrán szereplő milliszekundumok írási hibának kellene lenniük) és 263KB memóriát igényelnek, míg a PooledList <T>csak 36us és 0KB memóriára van szükség.




PooledDictionary<TKey, TValue>

Hozzáadjunk 10_0000 elemet a szótárhoz egy körben a Benchmarkban, . A .NET natív szótár<TKey, TValue> 11ms és 13MB memóriát igényel, míg a PooledDictionary<TKey, TValue> csak 7ms és 0MB memóriát igényel.




PooledSet<T>

Körözz végig a hash-gyűjteményen a Benchmarkban, adj hozzá 10_0000 elemet, . A .NET natív HashSet <T>5348ms és 2 MB memóriát igényel, míg a PooledSet <T>csak 4723ms és 0 MB memóriát igényel.




PooledStack<T>

Körözz végig a stacken a Benchmarkban, hogy hozzáadj 10_0000 elemet, . A .NET natív PooledStack <T>1079 ms és 2 MB sebességet igényel, míg a PooledStack <T>csak 633 ms és 0 MB memóriát igényel.




PooledQueue<T>

Körbefut a Benchmark ciklusain, hogy 10_0000 elemet adj hozzá a sorhoz, . A .NET natív <T>PooledQueue 681ms és 1MB kapacitást igényel, míg a PooledQueue <T>csak 408ms és 0MB memóriát igényel.




A jelenet nem kerül kézzel kiadásra

Ezen felül említettük, hogy a csoportosított gyűjteménytípust ki kell adni, de nem számít, ha nem adják ki, mert a GC újrahasznosítja.


A benchmark eredményei a következők:



A következtetés a fenti benchmark eredményekből vonható le.

A Pooled típusú gyűjtemény időben történő kiszabadítása alig indítja el a GC-t és a memóriát is elosztja, a fenti grafikon alapján csak 56 bájtot oszt le.
Még ha a Pooled típusú gyűjtemény nem is szabadul ki, mivel a medóriát a poolból osztja ki, a ReSize bővítési művelet során újra felhasználja a memóriát, és kihagyja a GC leallokált memória inicializációs lépését, ami viszonylag gyors.
A leglassabb a normál gyűjteménytípus használata, minden ReSize bővítési műveletnek új memóriateret kell igényelnie, és a GC-nek vissza kell szereznie az előző memóriateret is.


Elvelemzés

Ha olvastad az előző blogbejegyzésemet, állítsd be a gyűjteménytípusok kezdeti méretét, és elemezd a C# szótár megvalósítási elvét, tudhatod, hogy a .NET BCL fejlesztők ezeknek az alapvető gyűjteménytípusoknak az alap adatstruktúráit használják arrayk a nagy teljesítményű véletlenszerű hozzáféréshez, vegyük például a <T>Listet.

Hozz létre egy új tömböt a hozzáadott elemek tárolására.
Ha nincs elég hely a tömbben, a bővítési művelet elindul, hogy kétszer a tér méretét kérje.
A konstruktor kód a következő, és látható, hogy egy általános tömb, amelyet közvetlenül létrehoznak:


Tehát ha memóriát akarsz megosztani, csak azt kell megváltoztatnod, ahol az új kulcsszó alkalmazása az osztálykönyvtárban található, hogy a csoportos alkalmazást használd. Itt osztom meg veled. A NET BCL egy ArrayPool nevű típus, amely egy újrahasználható általános példányokból álló tömberőforrás-készletet biztosít, amelyekkel csökkenthetik a GC terhelését és javíthatják a teljesítményt gyakori tömblétrehozás és megsemmisítés esetén.

A Pooled típusunk mögöttes rétege az ArrayPool erőforrás-poolok megosztására, és a konstruktorból láthatjuk, hogy alapértelmezés szerint az <T>ArrayPool-ot használja. Shared arrayobjektumok hozzárendelésére, és természetesen létrehozhatsz saját ArrayPool-ot is, hogy használd.


Ezen felül, amikor kapacitásigazítási műveletet (bővítést) végzünk, a régi tömb visszakerül a szál poolba, és az új tömböt is beszerezik a poolból.

Ezen felül a szerző a Span-t használja az olyan API-k optimalizálására, mint az Add és Insert, hogy jobb véletlen hozzáférési teljesítményt nyújtson. Ezen felül hozzáadták a TryXXX sorozatú API-t, így kényelmesebb módon tudod használni. Például a Lista <T>osztály akár <T>170 módosítással rendelkezik a PooledListhez képest.



összefoglalás

Valódi online használatunkban a natív gyűjteménytípust a Pooled által biztosított gyűjteménytípusra cserélhetjük, ami nagyon hasznos a memóriahasználat és a P95 késleltetés csökkentésében.
Ráadásul, még ha el is felejteed kiadni, a teljesítmény nem lesz sokkal rosszabb, mint a natív gyűjteménytípus használatával. Természetesen a legjobb szokás, ha időben kiengedjük.


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




Előző:A RecyclableMemoryStream nagy teljesítményű .NET streamelést biztosít
Következő:[Praciális harc] A szerver LibreSpeedet épít, hogy tesztelje a hálózati sebességet
Közzétéve: 2022-5-29 17:12:36 |
Tanuld meg
Közzétéve: 2022-6-20, 09:09:22 |
Ismerd meg a keveréket
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