Hoe Werkt het Geheugen Management Werken in C#?

0
869

Vergeleken met C++, C#’s garbage collector lijkt magie, en je kunt heel eenvoudig code te schrijven zonder je zorgen te maken over de onderliggende geheugen. Maar als je de zorg over de prestaties, weten hoe je van het .NET runtime beheert de RAM kan u helpen bij het schrijven van een code.

Value Types vs. Reference Types

Er zijn twee soorten van soorten in .NETTO, die rechtstreeks van invloed zijn op hoe de onderliggende geheugen wordt behandeld.

Value types zijn primitieve typen met vaste maten, zoals int, bool, float, double, enz. Ze zijn gepasseerd door de waarde, wat betekent dat als u belt someFunction(int arg), het argument is gekopieerd en verzonden over een nieuwe locatie in het geheugen.

Onder de motorkap, value types zijn (meestal) op de stack opgeslagen. Meestal geldt dit voor lokale variabelen, en er zijn tal van uitzonderingen, waar ze in plaats daarvan worden opgeslagen op de heap. Maar in alle gevallen, de plaats in het geheugen waar de waarde van het type zich bevindt in het bezit van de werkelijke waarde van die variabele.

De stack is gewoon een bijzondere locatie in het geheugen geïnitialiseerd met een standaard waarde, maar kunnen uitbreiden. De stack is een Last-in, First-out (LIFO) data structuur. Je kunt het zien als een emmer—variabelen worden toegevoegd aan de bovenkant van de emmer, en als ze gaan uit van de scope, .NETTO bereikt in de emmer en verwijdert ze een voor een tijd, totdat het wordt aan de onderkant.

De stack is een stuk sneller, maar het is nog steeds slechts een locatie in het RAM-geheugen, niet op een bijzondere locatie in de CPU-cache (hoewel het kleiner is dan de hoop, en als zodanig is het zeer waarschijnlijk te warm in de cache, die helpt met prestaties).

De stapel krijgt de meeste van de prestaties van de LIFO-structuur. Wanneer u een oproep naar een functie, worden alle variabelen die zijn gedefinieerd in die functie worden toegevoegd aan de stapel. Wanneer die functie retourneert en de variabelen uit te gaan van de draagwijdte, de stack wist alles af van die functie op. De runtime beheert deze met stack frames, waarin blokken geheugen voor verschillende functies. Stapel de toewijzingen zijn zeer snel, want het is gewoon het schrijven van een enkele waarde aan het einde van de stack frame.

Dit is ook waar de term “StackOverflow” vandaan komt, wat het resultaat is wanneer een functie bevat te veel geneste aanroepen en vult het hele stapel.

Reference types, echter zijn of te groot, geen vaste maten, of live te lang op de stapel. Meestal hebben ze de vorm van objecten en klassen die zijn gemaakt, maar ze bevat ook arrays en strings, die kunnen variëren in grootte.

Reference types als instances van de klassen zijn vaak geïnitialiseerd met de new keyword, die zorgt voor een nieuwe instantie van de klasse en geeft als resultaat een verwijzing naar het resultaat. U kunt deze instellen op een lokale variabele, die daadwerkelijk gebruik maakt van de stapel voor het opslaan van de verwijzing naar de locatie op de heap.

De heap kan uitbreiden en vullen totdat de computer onvoldoende geheugen heeft, dat maakt het ideaal voor het opslaan van een veel van de gegevens. Echter, het is ongeorganiseerde, en in C# moet het beheerd worden met een garbage collector om goed te werken. Heap-toewijzingen zijn ook langzamer dan stapel toewijzingen, hoewel ze nog steeds vrij snel.

Er zijn echter een aantal uitzonderingen op deze regels, anders value en reference types zou worden genoemd “stapel-types” en “heap soorten.”

  • Buitenste variabelen van lambda functies lokale variabelen van IEnumerator blokken, en de lokale variabelen van het asynchrone methoden worden allemaal opgeslagen op de heap.
  • Waarde type velden van de klassen op de lange termijn variabelen, en worden altijd opgeslagen op de heap. Ze zijn ook verpakt in een reference type, en zijn opgeslagen naast die verwijzing type.
  • Statische klasse velden zijn ook altijd opgeslagen op de heap.
  • Aangepaste structs zijn waarde typen, maar ze kunnen bevatten reference types zoals Lijsten en strijkers, die zijn opgeslagen op de heap als normaal. Het creëren van een kopie van de struct maakt een nieuw exemplaar en de toewijzing van alle referentie-typen op de heap.

De meest opmerkelijke uitzondering op de regel van “reference types die op de heap,” is het gebruik van stackalloc met Span – <T>, die handmatig worden toegewezen voor een blok van het geheugen op de stapel voor een tijdelijke array die zullen gereinigd worden van de stapel af als normaal, wanneer het gaat uit van de scope. Dit gaat voorbij aan een relatief dure heap-verdeling en minder druk geeft op de garbage collector in het proces. Het kan een hoop meer performant, maar het is een beetje van een geavanceerde functie, dus als je meer wilt weten over deze functie kunt u deze handleiding te lezen over hoe het gebruik van het goed, zonder dat een StackOverflow uitzondering.

Wat Is Garbage Collection?

De stack is heel georganiseerd, maar de hoop is rommelig. Zonder iets om het te beheren, dingen op de heap niet automatisch opgeschoond, wat leidt tot uw toepassing uit het geheugen door het nooit bevrijd te worden.

Natuurlijk, dat is een probleem, dat is de reden waarom de garbage collector bestaat. Het loopt op een thread op de achtergrond en regelmatig scans van uw aanvraag voor verwijzingen die niet meer aanwezig zijn op de stapel, die aangeven dat het programma is gestopt met de zorg over de gegevens waarnaar wordt verwezen. Het .NET runtime kan komen en schoon te maken, en shift geheugen rond in het proces om de heap meer georganiseerd.

Echter, deze magie komt op een kostprijs—garbage collection is traag en te duur. Het loopt op een thread op de achtergrond, maar er is een periode waarin de uitvoering van het programma moet worden gestopt voor het uitvoeren van de garbage collection. Dit is de afweging die wordt geleverd met het programmeren in C#; alles wat je kunt doen is proberen om te minimaliseren de vuilnis u maken.

In talen zonder een garbage collector, moet u handmatig schoon te maken na jezelf, wat sneller is in veel gevallen maar meer vervelend voor de programmeur. Dus, in zekere zin, een garbage collector is als een Roomba, die ruimt uw vloeren automatisch, maar is langzamer dan gewoon opstaan en stofzuigen.