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

Pohľad: 6846|Odpoveď: 2

[Zdroj] [Otoč]. .NET Performance Optimization - Collections.Pooled sa odporúča

[Kopírovať odkaz]
Zverejnené 29. 5. 2022 o 13:45:22 | | | |
Stručný úvod

Optimalizácia výkonu je spôsob, ako zabezpečiť, aby rovnaký počet požiadaviek bol spracovaný s menším počtom zdrojov, ktoré sú zvyčajne CPU alebo pamäť, a samozrejme spracovanie operačného systému IO, sieťová prevádzka, využitie disku a podobne. Ale väčšinou znižujeme spotrebu CPU a pamäte.
Obsah zdieľaný predtým má určité obmedzenia, je ťažké ho priamo transformovať, dnes vám chcem predstaviť jednoduchú metódu – stačí nahradiť niekoľko typov kolekcií, aby sa dosiahol efekt zlepšenia výkonu a zníženia pamäťovej náročnosti.
Dnes vám chcem predstaviť triednu knižnicu, totoTriedna knižnica sa volá Collections.Pooled, Ako je vidieť z názvu, ide o zdieľanú pamäť na dosiahnutie cieľa zníženia pamäťovej náročnosti a GC, a priamo uvidíme, aký je jeho výkon, a tiež vás vezmeme do zdrojového kódu, prečo prináša tieto zlepšenia výkonu.

Zbierky. Združené

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

Knižnica je založená na triedach v System.Collections.Generic, ktoré boli upravené tak, aby využívali nové <T>knižnice tried System.Span a System.Buffers.ArrayPool <T>s cieľom znížiť alokáciu pamäte, zlepšiť výkon a umožniť väčšiu interoperabilitu s modernými API.
Collections.Pooled podporuje .NET Standnd 2.0 (.NET Framework 4.6.1+), ako aj podporu pre . NET Core 2.1+. Rozsiahla sada jednotkových testov a benchmarkov bola portovaná z CoreFX.

Celkový počet testov: 27501. Virál: 27501. Neúspech: 0. Skip: 0.
Testovacia prevádzka bola úspešná.
Čas vykonania testu: 9,9019 sekundy

Ako používať

Túto knižnicu si môžete jednoducho nainštalovať cez Nuget, verziu NuGet.

V knižnici Collections.Pooled implementuje združené verzie pre typy kolekcií, ktoré bežne používame, ako ukazuje porovnanie s natívnymi .NET typmi.

. .NET nativeZbierky. Združenépoznámka
Zoznam<T>PooledList<T>Triedy generických kolekcií
Dictionary<TKey, TValue>PooledDictionary<TKey, TValue>Trieda všeobecného slovníka
HashSet<T>PooledSet<T>Generické triedy kolekcií hashov
Stoh<T>Stoh<T>Generické zásobníky
Front<T>PooledQueue<T>Generická kohorta

Pri použití stačí pridať príslušné . .NET natívna verzia s verziou Collections.Pooled, ako je uvedené v kóde nižšie:

Musíme však poznamenať, že typ Pooled implementuje rozhranie IDispose, ktoré vracia použitú pamäť do poolu prostredníctvom metódy Dispose(), takže po použití objektu Pooled musíme zavolať jeho metódu Dispose(). Alebo môžete použiť kľúčové slovo using var priamo.

Poznámka: Použite objekt kolekcie vo vnútri Collections.PooledNajlepšie je uvoľniť ho manuálne, ale nezáleží na tom, či ho neuvoľníte, zelená karta ho nakoniec recykluje, ale nedá sa vrátiť do poolu a nedosiahne to úsporu pamäte.
Keďže opätovne využíva pamäťový priestor pri vracaniu pamäťového priestoru do poolu, musí spracovať prvky v kolekcii a poskytuje enumeráciu nazvanú ClearMode na použitie, definovanú nasledovne:




V predvolenom nastavení môžete použiť predvolenú hodnotu Auto a ak existujú špeciálne výkonnostné požiadavky, môžete použiť Never po znalosti rizík.
Pre typy referencií a hodnotové typy obsahujúce referenčné typy musíme pri vrátení pamäťového priestoru do poolu vyprázdniť referenciu poľa, ak nie je vymazaná, GC nebude môcť uvoľniť túto časť pamäťového priestoru (pretože referencia prvku bola vždy držaná v poole), ak ide o čistý typ hodnoty, potom ju nie je možné vyprázdniť. V tomto článku popisujem rozdiel v ukladaní medzi referenčnými typmi a štruktúrovanými (typmi hodnôt) poľami, čisté hodnotové typy nemajú recykláciu objektových hlavičiek a nevyžadujú zásah GC.


. .NET Performance Optimization - Použitie alternatívnych tried štruktúry:Prihlásenie na hypertextový odkaz je viditeľné.

Porovnanie výkonu

Benchmark som nerobil sám, a výsledky skóre open source projektov, ktoré som priamo používal, boli 0 z hľadiska využitia pamäte mnohých projektov, čo bolo spôsobené tým, že poolovaná pamäť nemala žiadnu extra alokáciu.

PooledList<T>

Prejdite si prvky z roku 2048 pridané do sady v Benchmark, . .NET native List <T>vyžaduje 110us (podľa skutočných výsledkov benchmarku by milisekundy na obrázku mali byť administratívnou chybou) a 263KB pamäte, zatiaľ čo PooledList <T>potrebuje len 36us a 0KB pamäte.




PooledDictionary<TKey, TValue>

Pridajte 10_0000 prvkov do slovníka v slučke v Benchmark, . .NET natívny Dictionary<TKey, TValue> vyžaduje 11ms a 13MB pamäte, zatiaľ čo PooledDictionary<TKey, TValue> vyžaduje len 7ms a 0MB pamäte.




PooledSet<T>

Prejdite hash kolekciu v Benchmarku a pridajte 10_0000 prvkov, . Natívny .NET HashSet <T>vyžaduje 5348ms a 2MB, zatiaľ čo PooledSet <T>vyžaduje len 4723ms a 0MB pamäte.




PooledStack<T>

Prejdite zásobník v Benchmarku a pridajte 10_0000 prvkov, . .NET natívny PooledStack <T>vyžaduje 1079ms a 2MB, zatiaľ čo PooledStack <T>vyžaduje len 633ms a 0MB pamäte.




PooledQueue<T>

Prejdite slučky v Benchmarku, aby ste do fronty pridali 10_0000 prvkov. .NET <T>natívny PooledQueue vyžaduje 681ms a 1MB, zatiaľ čo PooledQueue <T>vyžaduje len 408ms a 0MB pamäte.




Scéna sa manuálne neuvoľňuje

Okrem toho sme spomenuli vyššie, že typ zhromadnenej kolekcie musí byť uvoľnený, ale nezáleží na tom, či nie je uvoľnený, pretože generálna zbierka bude recyklovať.


Výsledky benchmarku sú nasledovné:



Záver možno vyvodiť z vyššie uvedených výsledkov benchmarku.

Uvoľnenie kolekcie typov Pooled včas sotva spustí GC a pridelí pamäť, pričom z vyššie uvedeného grafu alokuje len 56 bajtov pamäte.
Aj keď kolekcia typov Pooled nie je uvoľnená, pretože prideľuje pamäť z poolu, stále použije pamäť počas operácie rozšírenia ReSize a preskočí krok inicializácie pamäte alokácie GC, ktorý je relatívne rýchly.
Najpomalšie je použiť normálny typ kolekcie, každá operácia rozšírenia ReSize musí aplikovať na nový pamäťový priestor a GC tiež musí získať späť predchádzajúci pamäťový priestor.


Analýza princípov

Ak ste čítali môj predchádzajúci blogový príspevok, mali by ste nastaviť počiatočnú veľkosť pre typy kolekcií a analyzovať implementačný princíp C# Dictionary, môžete vedieť, že vývojári .NET BCL používajú základné dátové štruktúry týchto základných typov kolekcií ako polia pre vysoko výkonný náhodný prístup, vezmime si <T>napríklad List.

Vytvorte nové pole na uloženie pridaných prvkov.
Ak v poli nie je dostatok miesta, operácia rozširovania sa spustí na požiadanie o dvojnásobok veľkosti priestoru.
Kód konštruktora je nasledovný a vidíte, že ide o generické pole vytvorené priamo:


Takže ak chcete poolovať pamäť, stačí zmeniť miesto, kde sa nová aplikácia kľúčových slov používa v knižnici tried, aby ste mohli použiť pooled application. Tu sa s vami o to podelím. NET BCL je typ nazývaný ArrayPool, ktorý poskytuje zdrojový fond poľa s opakovane použiteľnými generickými inštanciami, ktoré možno použiť na zníženie tlaku na GC a zlepšenie výkonu pri častom vytváraní a ničení poľa.

Základnou vrstvou nášho Pooled typu je použitie ArrayPool na zdieľanie zdrojov a z jeho konštruktora vidíme, že predvolene používa ArrayPool<T>. Zdieľate na priraďovanie objektov poľa a samozrejme si môžete vytvoriť vlastný ArrayPool na jeho použitie.


Okrem toho, pri vykonávaní operácie úpravy kapacity (expanzia) sa staré pole vráti do poolu vlákien a nové pole sa tiež získa z poolu.

Okrem toho autor používa Span na optimalizáciu API ako Add a Insert, čím im poskytuje lepší výkon pri náhodnom prístupe. Okrem toho bola pridaná API série TryXXX, takže ho môžete používať pohodlnejšie. Napríklad <T>trieda List <T>má až 170 modifikácií v porovnaní s PooledList.



súhrn

Pri našom skutočnom online používaní môžeme natívny typ kolekcie nahradiť typom kolekcie poskytovaným Pooled, čo je veľmi užitočné pri znižovaní spotreby pamäte a latencie P95.
Aj keď na to zabudnete, výkon nebude oveľa horší ako pri použití natívneho typu kolekcie. Samozrejme, najlepší zvyk je uvoľniť ho včas.


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




Predchádzajúci:RecyclableMemoryStream poskytuje vysokovýkonné .NET streamovanie
Budúci:[Praktický boj] Server vytvára LibreSpeed na testovanie rýchlosti siete
Zverejnené 29. 5. 2022 o 17:12:36 |
Nauč sa to
Zverejnené 2022-6-20 09:09:22 |
Nauč sa túto zmes
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