Vec<T> is een dynamische, groeiende array die elementen opslaat in een enkele gealloceerde (op de heap) geheugenblok. Het toevoegen van een nieuw element (push) verhoogt de lengte en indien nodig wordt er nieuwe geheugen toegewezen (herallocatie). Bij push wordt de capaciteit exponentieel verhoogd om voortdurende herallocaties te vermijden. Bij het verwijderen van een element (pop/remove) wordt de capaciteit niet automatisch verlaagd.
Een veelvoorkomend probleem is overmatige allocaties en herallocatie bij constante toevoegingen.
Voorbeeld van werken met vooraf toegewezen geheugen:
let mut v = Vec::with_capacity(1000); for i in 0..1000 { v.push(i); } assert_eq!(v.capacity(), 1000); }
Vraag: Wat gebeurt er met de capaciteit van vec na de aanroep van v.shrink_to_fit()? Zal het precies gelijk zijn aan de lengte?
Onjuist antwoord: Ja, altijd, na shrink_to_fit is de capaciteit == lengte.
Juist antwoord: Niet noodzakelijk, de implementatie van shrink_to_fit is een "verzoek" aan de allocator. Gewoonlijk streeft het ernaar om de minimaal mogelijke capaciteit te bereiken, maar er kunnen afhankelijk van de implementatie van de allocator bijzonderheden zijn (bijvoorbeeld, het kan hoger blijven dan de lengte).
Voorbeeld:
let mut v = Vec::with_capacity(10); for i in 0..5 { v.push(i); } v.shrink_to_fit(); // capaciteit ≥ lengte (5), maar het is niet gegarandeerd dat het == lengte is }
Verhaal
Een ontwikkelaar duwde herhaaldelijk objecten in Vec zonder de capaciteit in te stellen, wat leidde tot exponentiële groei van herallocatie bij grote gegevensvolumes, wat de hele verwerking in "zware" cycli vertraagde. Optimalisatie met
with_capacityverminderde de tijd met 10 keer.
Verhaal
Het team probeerde geheugen te besparen door regelmatig
shrink_to_fitaan te roepen na elke pop(). Dit leidde tot cycli van constante herallocaties/vrijgifte en degradeerde de prestaties, bijna leidend tot een DoS voor de service.
Verhaal
Ze lieten Vec als een veld in een structuur met interne verwijzingen naar zijn elementen. Na herallocatie (push boven de capaciteit) werden de verwijzingen ongeldig — de resulterende bugs waren moeilijk te traceren tot ze in productie werden uitgevoerd.