Dit artikel is een spiegelartikel van machinevertaling, klik hier om naar het oorspronkelijke artikel te gaan.

Bekijken: 6846|Antwoord: 2

[Bron] [Draai]. .NET Performance Optimization - Collections.Pooled wordt aanbevolen

[Link kopiëren]
Geplaatst op 29-5-2022 13:45:22 | | | |
Korte introductie

Prestatieoptimalisatie is hoe je ervoor zorgt dat hetzelfde aantal verzoeken wordt verwerkt met minder resources, die meestal CPU of geheugen zijn, en natuurlijk besturingssysteem-IO-handages, netwerkverkeer, schijfgebruik, enzovoort. Maar meestal verminderen we het CPU- en geheugengebruik.
De eerder gedeelde content heeft enkele beperkingen, het is moeilijk direct te transformeren, vandaag wil ik een eenvoudige methode met je delen: je hoeft slechts een paar verzamelingstypen te vervangen om het effect te bereiken van betere prestaties en het verminderen van geheugenvoetafdruk.
Vandaag wil ik een klasbibliotheek met jullie delen, dezeDe klasbibliotheek heet Collections.Pooled, Zoals uit de naam te zien is, wordt het doel bereikt door gepoold geheugen te verkleinen en het geheugenverlies te verminderen, en we zullen direct zien hoe de prestaties zijn, en we nemen u ook mee naar de broncode, waarom dit deze prestatieverbeteringen brengt.

Collecties. Gepoold

Projectlink:De hyperlink-login is zichtbaar.

De bibliotheek is gebaseerd op klassen in System.Collections.Generic, die zijn aangepast om gebruik te maken van de nieuwe System.Span <T>en System.Buffers.ArrayPool <T>klassebibliotheken met als doel de geheugentoewijzing te verminderen, de prestaties te verbeteren en meer interoperabiliteit met moderne API's mogelijk te maken.
Collections.Pooled ondersteunt .NET Stand 2.0 (.NET Framework 4.6.1+), evenals ondersteuning voor . NET Core 2.1+. Een uitgebreide set unittests en benchmarks is overgenomen van CoreFX.

Totaal aantal tests: 27.501. Via: 27501. Mislukking: 0. Skip: 0.
De proefrit was succesvol.
Testuitvoeringstijd: 9,9019 seconden

Hoe te gebruiken

Je kunt deze bibliotheek eenvoudig installeren via Nuget, NuGet Version.

In de Collections.Pooled-bibliotheek implementeert het gepoolde versies voor de collectietypen die we gewoonlijk gebruiken, zoals te zien is in de vergelijking met de .NET native types.

. .NET nativeCollecties. Gepooldopmerking
Lijst<T>PooledList<T>Generieke verzamelingsklassen
Woordenboek<TKey, TValue>PooledDictionary<TKey, TValue>Generieke woordenboekklasse
HashSet<T>PooledSet<T>Generieke hashverzamelingsklassen
Stapel<T>Stapel<T>Generieke stacks
Rij<T>PooledQueue<T>Generieke cohort

Bij gebruik hoeven we alleen de overeenkomstige toevoeging toe te voegen. .NET native versie met de Collections.Pooled-versie, zoals weergegeven in de onderstaande code:

We moeten echter opmerken dat het Pooled-type de IDispose-interface implementeert, die het gebruikte geheugen via de Dispose()-methode teruggeeft aan de pool, dus we moeten de Dispose()-methode aanroepen na gebruik van het Pooled collection-object. Of je kunt direct het sleutelwoord 'gebruikvar' gebruiken.

Opmerking: Gebruik het collectieobject binnen Collections.PooledHet is het beste om het handmatig vrij te geven, maar het maakt niet uit als je het niet vrijgeeft, de GC zal het uiteindelijk recyclen, maar het kan niet terug in de pool en het zal niet het geheugen besparen effect.
Omdat het geheugenruimte hergebruikt, moet het bij het teruggeven van geheugenruimte aan de pool de elementen in de collectie verwerken, en het biedt een enumeratie genaamd ClearMode voor gebruik, gedefinieerd als volgt:




Standaard kun je de standaardwaarde Auto gebruiken, en als er speciale prestatie-eisen zijn, kun je Never gebruiken nadat je de risico's kent.
Voor referentietypen en waardetypen die referentietypes bevatten, moeten we de arrayreferentie leegmaken wanneer we de geheugenruimte terugbrengen naar de pool; als het niet is gewist, kan de GC dit deel van de geheugenruimte niet vrijmaken (omdat de referentie van het element altijd door de pool is gehold). Als het een puur waardetype is, kan het niet worden leeggehaald. In dit artikel beschrijf ik het opslagverschil tussen referentietypes en struct (waardetype) arrays; pure waardetypen hebben geen objectheaderrecycling en vereisen geen GC-interventie.


. .NET Performance Optimization - Gebruik struct alternatieve klassen:De hyperlink-login is zichtbaar.

Prestatievergelijking

Ik heb Benchmark niet alleen gedaan, en de lopende scoreresultaten van open source projecten die ik direct gebruikte waren 0 voor het geheugengebruik van veel projecten, omdat het gebruikte gepoolde geheugen geen extra toewijzing had.

PooledList<T>

Loop door de 2048-elementen die aan de set zijn toegevoegd in Benchmark, . .NET native List <T>vereist 110us (volgens de daadwerkelijke benchmarkresultaten zouden de milliseconden in de figuur een administratieve fout moeten zijn) en 263KB geheugen, terwijl PooledList <T>slechts 36us en 0KB geheugen nodig heeft.




PooledDictionary<TKey, TValue>

Voeg 10_0000 elementen toe aan het woordenboek in een lus in Benchmark, . .NET native Dictionary<TKey, TValue> vereist 11ms en 13MB geheugen, terwijl PooledDictionary<TKey, TValue> slechts 7ms en 0MB geheugen vereist.




PooledSet<T>

Voeg door de hashcollectie in Benchmark 10_0000 elementen, . De .NET native HashSet <T>vereist 5348ms en 2MB, terwijl de PooledSet <T>slechts 4723ms en 0MB geheugen vereist.




PooledStack<T>

Loop door de stack in Benchmark om 10_0000 elementen toe te voegen, . .NET native PooledStack <T>vereist 1079ms en 2MB, terwijl PooledStack <T>slechts 633ms en 0MB geheugen vereist.




PooledQueue<T>

Loop door de lussen in Benchmark om 10_0000 elementen aan de wachtrij toe te voegen, . .NET native <T>PooledQueue vereist 681ms en 1MB, terwijl PooledQueue <T>slechts 408ms en 0MB geheugen vereist.




De scène wordt niet handmatig vrijgegeven

Daarnaast noemden we hierboven al dat het type verzameling moet worden vrijgegeven, maar het maakt niet uit als het niet wordt vrijgegeven, want de GC zal recyclen.


De resultaten van de Benchmark zijn als volgt:



De conclusie kan worden getrokken uit de bovenstaande Benchmark-resultaten.

Het vrijgeven van de Pooled typecollectie in de tijd activeert nauwelijks GC en geeft geheugen allocatie; uit bovenstaande grafiek wordt slechts 56 byte geheugen toegewezen.
Zelfs als de Pooled type collectie niet wordt vrijgegeven, zal het geheugen toch hergebruiken tijdens de ReSize-uitbreidingsoperatie omdat het geheugen uit de pool toewijst en de GC-allokatie-geheugeninitialisatiestap overslaan, die relatief snel is.
De langzaamste is om het normale verzamelingstype te gebruiken; elke ReSize-uitbreidingsoperatie moet worden toegepast voor nieuwe geheugenruimte, en de GC moet ook de vorige geheugenruimte terugwinnen.


Principeanalyse

Als je mijn vorige blogpost hebt gelezen, moet je de initiële grootte van collectietypen instellen en het implementatieprincipe van C# Dictionary analyseren; je weet dat .NET BCL-ontwikkelaars de onderliggende datastructuren van deze basiscollectietypen gebruiken als arrays voor high-performance random access, laten we List <T>als voorbeeld nemen.

Maak een nieuwe array aan om de toegevoegde elementen op te slaan.
Als er niet genoeg ruimte in de array is, wordt de uitbreidingsoperatie geactiveerd om twee keer de ruimtegrootte te vragen.
De constructorcode is als volgt, en je kunt zien dat het een generieke array is die direct is gemaakt:


Dus als je geheugen wilt poolen, hoef je alleen de plek te veranderen waar de nieuwe trefwoordapplicatie in de classbibliotheek wordt gebruikt om de pooled application te gebruiken. Hier deel ik het met jullie. NET BCL is een type genaamd ArrayPool, dat een array-resourcepool van herbruikbare generieke instanties biedt, die kunnen worden gebruikt om de druk op GC te verminderen en de prestaties te verbeteren bij frequente arraycreatie en -vernietiging.

De onderliggende laag van ons Pooled-type is om ArrayPool te gebruiken om resource pools te delen, en uit de constructor kunnen we zien dat het standaard ArrayPool gebruikt<T>. Gedeeld om array-objecten toe te wijzen, en natuurlijk kun je ook je eigen ArrayPool maken om het te gebruiken.


Daarnaast wordt bij het uitvoeren van een capaciteitsaanpassingsoperatie (uitbreiding) de oude array teruggegeven aan de threadpool en wordt de nieuwe array ook uit de pool verkregen.

Daarnaast gebruikt de auteur Span om API's zoals Add en Insert te optimaliseren, zodat ze betere prestaties bij willekeurige toegang krijgen. Daarnaast is de TryXXX-serie API toegevoegd, zodat je deze op een handigere manier kunt gebruiken. Zo <T>heeft de List-klasse <T>tot 170 aanpassingen vergeleken met PooledList.



samenvatting

In ons daadwerkelijke online gebruik kunnen we het native collectietype vervangen door het collectietype dat door Pooled wordt geleverd, wat erg handig is om geheugengebruik en P95-latentie te verminderen.
Ook als je vergeet het vrij te geven, zal de prestatie niet veel slechter zijn dan met het native collectietype. Natuurlijk is de beste gewoonte om het op tijd los te laten.


Origineel:De hyperlink-login is zichtbaar.




Vorig:RecyclableMemoryStream biedt high-performance .NET-streaming
Volgend:[Praktische gevechten] De server bouwt LibreSpeed om de netwerksnelheid te testen
Geplaatst op 29-5-2022 17:12:36 |
Leer het
Geplaatst op 20-6-2022 09:09:22 |
Leer de mix
Disclaimer:
Alle software, programmeermaterialen of artikelen die door Code Farmer Network worden gepubliceerd, zijn uitsluitend bedoeld voor leer- en onderzoeksdoeleinden; De bovenstaande inhoud mag niet worden gebruikt voor commerciële of illegale doeleinden, anders dragen gebruikers alle gevolgen. De informatie op deze site komt van het internet, en auteursrechtconflicten hebben niets met deze site te maken. Je moet bovenstaande inhoud volledig van je computer verwijderen binnen 24 uur na het downloaden. Als je het programma leuk vindt, steun dan de echte software, koop registratie en krijg betere echte diensten. Als er sprake is van een inbreuk, neem dan contact met ons op via e-mail.

Mail To:help@itsvse.com