Affaldsopsamling [ 1] i programmering er en form for automatisk hukommelseshåndtering . En speciel proces , kaldet garbage collector , frigiver periodisk hukommelse ved at fjerne genstande , der er blevet unødvendige fra den .
Automatisk affaldsindsamling forbedrer sikkerheden ved hukommelsesadgang .
Garbage collection blev første gang anvendt af John McCarthy i 1959 i et programmeringsmiljø i det funktionelle programmeringssprog , han udviklede, Lisp . Efterfølgende blev det brugt i andre programmeringssystemer og sprog, hovedsageligt i funktionelle og logiske . Behovet for affaldsindsamling i disse typer sprog skyldes det faktum, at strukturen af sådanne sprog gør det ekstremt ubelejligt at holde styr på levetiden for objekter i hukommelsen og manuelt administrere det. Lister , der er meget udbredt på disse sprog og komplekse datastrukturer baseret på dem , bliver konstant oprettet, tilføjet, udvidet, kopieret under driften af programmer, og det er vanskeligt korrekt at bestemme tidspunktet for sletning af et objekt.
Industrielle procedure- og objektsprog brugte ikke affaldsindsamling i lang tid. Fortrinsret blev givet til manuel hukommelsesstyring, som mere effektiv og forudsigelig. Men siden anden halvdel af 1980'erne er skraldeindsamlingsteknologi blevet brugt i både direktiv ( imperativt ) og objektprogrammeringssprog, og siden anden halvdel af 1990'erne har et stigende antal skabte sprog og miljøer med fokus på applikationsprogrammering bl.a. en indsamlingsmekanisme-skrald enten som den eneste eller som en af de tilgængelige dynamiske hukommelsesstyringsmekanismer. Det bruges i øjeblikket i Oberon , Java , Python , Ruby , C# , D , F# , Go og andre sprog.
Den traditionelle måde for direktivsprog at administrere hukommelse på er manuel. Dens essens er som følger:
I ethvert sprog, der tillader skabelsen af objekter i dynamisk hukommelse, er der to potentielle problemer: dinglende referencer og hukommelseslækager .
En dinglende pointer er en reference til et objekt, der allerede er blevet fjernet fra hukommelsen. Efter sletning af et objekt bliver alle referencer til det gemt i programmet "dinglende". Hukommelsen, der tidligere var optaget af et objekt, kan blive overdraget til operativsystemet og blive utilgængelig eller bruges til at allokere et nyt objekt i det samme program. I det første tilfælde vil et forsøg på at få adgang til et "dinglende" link udløse hukommelsesbeskyttelsesmekanismen og nedbryde programmet, og i det andet tilfælde vil det føre til uforudsigelige konsekvenser.
Forekomsten af dinglende referencer er normalt resultatet af en forkert vurdering af et objekts levetid: programmøren kalder kommandoen for at slette objektet, før dets brug ophører.
Ved at oprette et objekt i dynamisk hukommelse vil programmøren muligvis ikke slette det, efter at brugen er fuldført. Hvis en variabel, der refererer til et objekt, tildeles en ny værdi, og der ikke er andre referencer til objektet, bliver den programmatisk utilgængelig, men fortsætter med at optage hukommelse, fordi slettekommandoen ikke blev kaldt. Denne situation kaldes en hukommelseslækage .
Hvis objekter, som referencer går tabt, konstant skabes i programmet, så viser en hukommelseslæk sig sig i en gradvis stigning i mængden af brugt hukommelse; hvis programmet kører i lang tid, vokser mængden af hukommelse, der bruges af det konstant, og efter nogen tid bremses systemet mærkbart (på grund af behovet for at bruge swap til enhver hukommelsestildeling ), eller programmet opbruger den tilgængelige adresseplads og slutter med en fejl.
Hvis computerhukommelsen var uendelig , ville det være muligt blot at efterlade unødvendige objekter i hukommelsen. Automatisk hukommelseshåndtering med affaldsopsamling - emulering af sådan en uendelig computer på en begrænset hukommelse [2] . Mange af begrænsningerne for skraldeopsamlere (der er ingen garanti for, at en færdiggører vil udføre; den administrerer kun hukommelsen, ikke andre ressourcer) stammer fra denne metafor.
På et affaldsopsamlet system er det programafviklingsmiljøets ansvar at deallokere hukommelse. Programmereren opretter kun dynamiske objekter og bruger dem, han er måske ligeglad med at slette objekter, da miljøet gør det for ham. For at gøre dette er et specielt softwaremodul kaldet "skraldsamleren" inkluderet i runtime-miljøet. Dette modul kører med jævne mellemrum, bestemmer hvilke af objekterne, der er oprettet i dynamisk hukommelse, der ikke længere bruges, og frigør den hukommelse, de optager.
Hyppigheden af at køre affaldssamleren bestemmes af systemets egenskaber. Samleren kan køre i baggrunden, startende når programmet er inaktivt (for eksempel når programmet er inaktivt, venter på brugerinput). Skraldeopsamleren kører ubetinget og stopper programafviklingen ( Stop- the -world ), når den næste hukommelsesallokeringsoperation ikke kan udføres på grund af det faktum, at al tilgængelig hukommelse er opbrugt. Når hukommelsen er frigivet, genoptages den afbrudte hukommelsestildeling, og programmet fortsætter med at blive udført. Hvis det viser sig, at hukommelsen ikke kan frigøres, afslutter kørselstiden programmet med en fejlmeddelelse "Monteret af hukommelse".
Det ville være optimalt at fjerne objekter fra hukommelsen, som ikke vil blive tilgået i løbet af yderligere programdrift. Imidlertid er identifikation af sådanne objekter umulig, da det reduceres til et algoritmisk uløseligt standsningsproblem (for dette er det tilstrækkeligt at antage, at noget objekt X vil blive brugt, hvis og kun hvis programmet P fuldføres med succes ). Derfor bruger skraldesamlere konservative skøn for at sikre, at en genstand ikke vil blive brugt i fremtiden.
Normalt er kriteriet for, at et objekt stadig er i brug, tilstedeværelsen af referencer til det: hvis der ikke er flere referencer til dette objekt i systemet, så kan det naturligvis ikke længere bruges af programmet og kan derfor slettet. Dette kriterium bruges af de fleste moderne affaldssamlere og kaldes også for objekttilgængelighed . Det er teoretisk set ikke det bedste, da tilgængelige objekter ifølge den også omfatter de objekter, der aldrig vil blive brugt, men som der stadig er referencer til, men det garanterer beskyttelse mod udseendet af "dinglende" referencer og kan implementeres ganske effektivt .
Uformelt kan følgende rekursive definition af et tilgængeligt objekt gives:
Flagalgoritme
En simpel algoritme til at bestemme tilgængelige objekter, Mark and Sweep-algoritmen, er som følger:
Hvis to eller flere objekter refererer til hinanden, men ingen af disse objekter refereres udefra, anses hele gruppen for at være uopnåelig. Denne algoritme giver dig mulighed for at garantere fjernelse af grupper af objekter, hvis brug er ophørt, men hvor der er links til hinanden. Sådanne grupper omtales ofte som "isolationsøer".
ReferenceoptællingsalgoritmeEn anden variant af tilgængelighedsalgoritmen er den sædvanlige referencetælling . Dens brug sænker referencetildelingsoperationer, men definitionen af tilgængelige objekter er triviel - disse er alle objekter, hvis referencetællerværdi overstiger nul. Uden yderligere afklaringer fjerner denne algoritme, i modsætning til den forrige, ikke cyklisk lukkede kæder af forældede objekter, der har forbindelser til hinanden.
Når et sæt uopnåelige objekter er defineret, kan skraldeopsamleren deallokere den hukommelse, der er optaget af dem, og lade resten være som den er. Det er også muligt at flytte alle eller en del af de resterende objekter til andre områder af hukommelsen efter frigørelse af hukommelse, og samtidig opdatere alle referencer til dem. Disse to implementeringer omtales som henholdsvis ikke -flytning og flytning .
Begge strategier har både fordele og ulemper.
Hukommelsestildeling og deallokeringshastighed En skraldeopsamler, der ikke flytter, frigiver hukommelse hurtigere (fordi den bare markerer de passende hukommelsesblokke som ledige), men bruger mere tid på at tildele den (fordi hukommelsen bliver fragmenteret, og allokeringen skal finde den rigtige mængde af passende størrelse blokke i hukommelsen ). Flytsamleren tager relativt længere tid at indsamle skrald (det tager ekstra tid at defragmentere hukommelsen og ændre alle referencer til de objekter, der flyttes), men flytningen giver mulighed for en ekstremt enkel og hurtig ( O(1) ) hukommelsesallokeringsalgoritme. Under defragmentering flyttes objekter for at opdele al hukommelse i to store områder - optaget og fri, og en pegepind til deres grænse gemmes. For at tildele ny hukommelse er det nok bare at flytte denne grænse og returnere et stykke fra begyndelsen af ledig hukommelse. Adgangshastighed til objekter i dynamisk hukommelse Objekter, hvis felter er delte, kan placeres tæt på hinanden i hukommelsen af flyttesamleren. Så er de mere tilbøjelige til at være i processorcachen på samme tid, hvilket vil reducere antallet af adgange til relativt langsom RAM . Udenlandsk kodekompatibilitet Den flyttende skraldeopsamler forårsager problemer ved brug af kode, der ikke administreres af automatisk hukommelsesstyring (en sådan kode kaldes fremmed i traditionel terminologi eller uadministreret i Microsoft - terminologi ) . En pointer til hukommelse, der er allokeret på et system med en ikke-flyttende samler, kan simpelthen videregives til fremmed kode til brug, mens man holder på mindst én regelmæssig reference til objektet, så samleren ikke sletter det. Den bevægelige samler ændrer placeringen af objekter i hukommelsen og ændrer synkront alle referencer til dem, men den kan ikke ændre referencer i fremmed kode, som et resultat vil referencerne, der sendes til den fremmede kode efter flytning af objektet, blive forkerte. For at arbejde med fremmed kode bruges forskellige specielle teknikker, for eksempel er pinning en eksplicit blokering af en genstand, der forbyder dens bevægelse under affaldsindsamling.Som praksis viser, bliver nyligt oprettede objekter oftere utilgængelige end objekter, der eksisterer i lang tid. I overensstemmelse med dette mønster opdeler mange moderne skraldesamlere alle genstande i flere generationer - en række genstande med en tæt levetid. Så snart hukommelsen, der er tildelt en af generationerne, løber tør, i denne generation og i alle "yngre" generationer, søges der efter uopnåelige objekter. Alle fjernes, og de resterende overføres til den "ældre" generation.
Brug af generationer reducerer cyklustiden for affaldsindsamling ved at reducere antallet af objekter, der scannes under indsamlingen, men denne metode kræver, at køretiden holder styr på referencer mellem forskellige generationer.
For at et program kan bruge skraldindsamling, skal en række betingelser være opfyldt, der vedrører sproget, runtime-miljøet og selve opgaven.
Behovet for en løbetur med en skraldeopsamler Naturligvis kræver affaldsindsamling et dynamisk miljø, der understøtter programmets eksekvering, og tilstedeværelsen af en affaldsopsamler i dette miljø. For fortolkede sprog eller sprog kompileret til virtuel maskine-bytekode, kan skraldeopsamleren inkluderes i sprog- eller bytekodefortolkerkoden, men for sprog kompileret til objektkode er skraldeopsamleren tvunget til at blive en del af systemet bibliotek, som er forbundet (statisk eller dynamisk) med programkode, når der oprettes en eksekverbar fil, hvilket øger programmets størrelse og dets indlæsningstid. Understøttelse af programmeringssprog Skraldeopsamleren kan kun fungere korrekt, når den nøjagtigt kan spore alle referencer til alle oprettede objekter. Hvis sproget tillader konvertering af referencer (pointere) til andre datatyper (heltal, arrays af bytes osv.), såsom C / C++ , bliver det naturligvis umuligt at spore brugen af sådanne konverterede referencer, og affaldsindsamling bliver meningsløs - den beskytter ikke mod "hængende" links og hukommelseslækager. Derfor begrænser skraldeindsamlingsorienterede sprog normalt betydeligt friheden til at bruge pointere, adresseregning, konverteringer af pointertyper til andre datatyper. Nogle af dem har slet ikke en "pointer"-datatype, nogle af dem har, men tillader hverken typekonverteringer eller ændringer. Teknisk godkendelse af kortvarige forsinkelser i programmernes arbejde Affaldsindsamling udføres med jævne mellemrum, normalt på ukendte tidspunkter. Hvis suspendering af programmet i en periode, der kan sammenlignes med tidspunktet for indsamling af affald, kan føre til kritiske fejl , er det naturligvis umuligt at bruge affaldsindsamling i en sådan situation. At have en reserve af ledig hukommelse Jo mere hukommelse der er til rådighed for kørselstiden, jo sjældnere kører skraldeopsamleren, og jo mere effektiv er den. At køre en skraldeopsamler på et system, hvor mængden af hukommelse, der er tilgængelig for skraldeopsamleren, nærmer sig programmets spidsbelastning, kan være ineffektivt og spild. Jo mindre hukommelsesoverskud, jo oftere kører samleren, og jo længere tid tager det at køre den. Faldet i programmets ydeevne i denne tilstand kan være for markant.I modsætning til hvad der ofte bliver sagt, frigør tilstedeværelsen af affaldsopsamling slet ikke programmøren for alle problemer med hukommelsesstyring.
Frigiv andre ressourcer optaget af objektet Ud over dynamisk hukommelse kan et objekt eje andre ressourcer, nogle gange mere værdifulde end hukommelse. Hvis et objekt åbner en fil ved oprettelse, skal det lukke den, når brugen er afsluttet; hvis det opretter forbindelse til et DBMS, skal det afbryde forbindelsen. I systemer med manuel hukommelseshåndtering gøres dette umiddelbart før objektet fjernes fra hukommelsen, oftest i destruktorerne af de tilsvarende objekter. I systemer med affaldsindsamling er det normalt muligt at udføre noget kode lige før sletning af et objekt, de såkaldte finalizers , men de er ikke egnede til at frigøre ressourcer, da sletningsøjeblikket ikke kendes på forhånd, og det kan vende ud af, at ressourcen frigives meget senere, end objektet ophører med at blive brugt. I sådanne tilfælde skal programmøren stadig spore brugen af objektet manuelt og manuelt udføre operationer for at frigive de ressourcer, som objektet optager. I C# er der en grænseflade specifikt til dette formål , IDisposablei Java- .AutoCloseable Hukommelsestab I systemer med affaldsindsamling kan der også opstå hukommelseslækager, selvom de har en lidt anden karakter. En reference til et ubrugt objekt kan gemmes i et andet objekt, der bliver brugt, og bliver en slags "anker", der holder det unødvendige objekt i hukommelsen. For eksempel føjes det oprettede objekt til samlingen, der bruges til hjælpeoperationer, og ophører derefter med at blive brugt, men fjernes ikke fra samlingen. Samlingen holder referencen, objektet forbliver tilgængeligt og indsamles ikke affald. Resultatet er den samme hukommelseslækage. For at eliminere sådanne problemer kan runtime understøtte en særlig funktion - de såkaldte svage referencer . Svage referencer holder ikke objektet og bliver til null, så snart objektet forsvinder – så koden skal forberedes på, at referencen en dag peger ingen steder hen. Tab af effektivitet i driften med hyppig hukommelsestildeling og -deallokering Nogle handlinger, der er ret harmløse på systemer med manuel hukommelsesstyring, kan medføre uforholdsmæssigt store omkostninger på systemer med affaldsindsamling. Et klassisk eksempel på et sådant problem er vist nedenfor. String out = "" ; // Det antages, at strenge indeholder et stort antal korte strenge, // hvorfra du skal samle en stor streng i ud-variablen. for ( String str : strings ) { out += str ; // Denne kode vil skabe // en ny strengvariabel hver iteration og allokere hukommelse til den. } Denne Java-kode ser ud som om ud-variablen, der er oprettet én gang, "tilføjes" med en ny linje hver gang i løkken. Faktisk er strenge i Java uforanderlige, så i denne kode vil følgende ske ved hver gang i løkken:Sammenlignet med manuel hukommelseshåndtering er affaldsindsamling sikrere, fordi det forhindrer hukommelseslækager og dinglende links fra utidig bortskaffelse af genstande. Det forenkler også selve programmeringsprocessen .
Skraldopsamling menes at reducere hukommelseshåndteringsomkostningerne betydeligt sammenlignet med sprog, der ikke implementerer det. Ifølge en undersøgelse [3] bruger C-programmører 30% - 40% af deres samlede udviklingstid (eksklusive fejlretning) alene på hukommelseshåndtering. Der er dog undersøgelser med modsatte konklusioner, for eksempel i [4] hedder det, at den reelle forskel i hastigheden af softwareudvikling i C++, hvor der ikke er automatisk affaldsindsamling, og i Java, hvor det er implementeret , Er lille.
Tilstedeværelsen af en skraldsamler i en uerfaren udvikler kan skabe en falsk tro på, at han overhovedet ikke behøver at være opmærksom på hukommelseshåndtering. Selvom skraldeopsamleren reducerer problemer med hukommelsesfejl, eliminerer den dem ikke fuldstændigt, og de, der fortsætter, vises ikke som åbenlyse fejl, såsom en generel beskyttelsesfejl , men som spildt hukommelse, når et program kører. Et typisk eksempel: hvis programmøren har mistet overblikket over, at der er mindst én ikke-nullbar pointer tilbage på objektet i det globale scope, vil et sådant objekt aldrig blive slettet; at finde sådan en pseudo-lækage kan være meget vanskelig.
Ofte er det afgørende ikke kun at sikre, at ressourcen er frigivet, men også at sikre, at den bliver frigivet, før en anden procedure kaldes - for eksempel åbne filer, indtastninger i kritiske sektioner. Forsøg på at give kontrol over disse ressourcer til skraldeopsamleren (via færdigbehandlere ) vil være ineffektive eller endda forkerte, så du er nødt til at administrere dem manuelt. For nylig, selv på sprog med en skraldeopsamler, er der blevet introduceret en syntaks, der garanterer udførelse af "oprydningskode" (for eksempel en speciel "destruktor"-metode), når en variabel, der refererer til et objekt, går uden for rækkevidde.
I mange tilfælde er systemer med affaldsindsamling mindre effektive, både med hensyn til hastighed og hukommelsesforbrug (hvilket er uundgåeligt, da skraldeopsamleren selv bruger ressourcer og har brug for noget overskydende ledig hukommelse for at fungere korrekt). Derudover er det i systemer med affaldsindsamling sværere at implementere lavniveaualgoritmer, der kræver direkte adgang til computerens RAM, da den frie brug af pointere er umulig, og direkte hukommelsesadgang kræver specielle grænseflader skrevet på lavniveausprog . På den anden side bruger moderne affaldsopsamlede systemer meget effektive hukommelsesstyringsalgoritmer med minimal overhead. Det er også umuligt ikke at tage højde for, at nu er RAM relativt billig og tilgængelig. Under sådanne forhold er situationer, hvor det er omkostningerne til affaldsindsamling, der bliver afgørende for programmets effektivitet, yderst sjældne.
Den væsentlige fordel ved affaldsindsamling er, når dynamisk skabte objekter lever i lang tid, duplikeres mange gange, og referencer til dem sendes mellem forskellige dele af programmet. Under sådanne forhold er det ret svært at bestemme det sted, hvor objektet er ophørt med at blive brugt, og det kan slettes. Da dette netop er situationen med den udbredte brug af dynamisk skiftende datastrukturer (lister, træer, grafer), er affaldsindsamling nødvendig i funktionelle og logiske sprog, der i vid udstrækning bruger sådanne strukturer, såsom Haskell , Lisp eller Prolog . Brugen af affaldsindsamling i traditionelle imperative sprog (baseret på et strukturelt paradigme, måske suppleret med objektfaciliteter) er bestemt af den ønskede balance mellem enkelheden og hastigheden af programudvikling og effektiviteten af dets udførelse.
Understøttelse på nogle imperative sprog til automatisk at kalde destruktoren, når et objekt går ud af syntaktisk rækkevidde ( C++ [5] , Ada , Delphi ) giver dig mulighed for at placere hukommelsesfrigivelseskoden i destruktoren og være sikker på, at den bliver kaldt alligevel . Dette giver dig mulighed for at koncentrere farlige steder inden for implementeringen af klassen og kræver ikke ekstra ressourcer, selvom det stiller højere krav til programmørens kvalifikationer. Samtidig bliver det muligt sikkert at frigive andre ressourcer optaget af objektet i destruktoren.
Et alternativ til skraldindsamling er teknologien med at bruge " smarte referencer ", når en reference til et dynamisk objekt selv holder styr på antallet af brugere og automatisk sletter objektet, når dette tal bliver nul. Et velkendt problem med "smarte referencer" er, at under forhold, hvor programmet konstant skaber mange små kortlivede objekter i hukommelsen (for eksempel ved behandling af listestrukturer), taber de til skraldopsamling i ydeevne.
Siden 1960'erne har der været regionsbaseret hukommelsesstyring , en teknologi, hvor hukommelsen er opdelt i relativt store fragmenter kaldet regioner , og allerede inden for regionerne allokeres hukommelse til individuelle objekter. Ved manuel styring oprettes og slettes regioner af programmøren selv, med automatisk styring bruges forskellige typer konservative estimater til at bestemme, hvornår alle objekter allokeret indenfor regionen ophører med at blive brugt, hvorefter hukommelsesstyringssystemet sletter hele regionen. For eksempel oprettes en region, hvor hukommelse tildeles til alle objekter, der er oprettet inden for et bestemt omfang, ikke sendes udenfor, og denne region ødelægges med én kommando, når programafviklingen forlader dette omfang. Overgangen i hukommelsesstyring (uanset om manuel eller automatisk) fra individuelle objekter til større enheder giver os i mange tilfælde mulighed for at forenkle regnskabet for objekters levetid og samtidig reducere overheadomkostninger. Implementeringer (af varierende grader af automatisering) af regional hukommelsesstyring findes for mange programmeringssprog, herunder ML , Prolog , C , Cyclone .
Programmeringssproget Rust tilbyder konceptet "ejerskab" baseret på compilerens stramme kontrol over objekternes levetid og omfang. Ideen er, at når et objekt oprettes, bliver den variabel, der er tildelt en reference til det, "ejer" af det pågældende objekt, og omfanget af ejervariablen begrænser objektets levetid. Når man forlader ejerens omfang, slettes objektet automatisk. Ved at tildele en objektreference til en anden variabel kan den "lånes", men lån er altid midlertidigt og skal gennemføres inden for objektets ejers levetid. "Ejerskab" kan overføres til en anden variabel (for eksempel kan et objekt oprettes inde i en funktion og returneres som et resultat), men den oprindelige ejer mister adgang til objektet. Tilsammen er reglerne designet til at sikre, at et objekt ikke kan ændres ukontrolleret gennem uvedkommende referencer. Compileren sporer statisk objekters levetid: Enhver handling, der endda potentielt kan føre til at gemme en reference til et objekt, efter at dets ejer går uden for scope, fører til en kompileringsfejl, som eliminerer forekomsten af "dinglende referencer" og hukommelseslækager. Denne tilgang komplicerer programmeringsteknikken (hhv. gør det vanskeligt at lære sproget), men eliminerer behovet for både manuel tildeling og deallokering af hukommelse og brugen af affaldsindsamling.
Affaldsopsamling som en uundværlig egenskab ved programafviklingsmiljøet bruges i sprog baseret på det deklarative paradigme , såsom LISP , ML , Prolog , Haskell . Dets nødvendighed i dette tilfælde skyldes selve naturen af disse sprog, som ikke indeholder værktøjer til manuel styring af objekters levetid og ikke har mulighed for naturlig integration af sådanne værktøjer. Den grundlæggende komplekse datastruktur i sådanne sprog er normalt en dynamisk enkeltforbundet liste bestående af dynamisk allokerede listeceller. Lister bliver konstant oprettet, kopieret, duplikeret, kombineret og opdelt, hvilket gør det næsten umuligt manuelt at administrere levetiden for hver tildelt listecelle.
På imperative sprog er affaldsindsamling én mulighed, sammen med manuelle og nogle alternative hukommelseshåndteringsteknikker. Her betragtes det som et middel til at forenkle programmeringen og forhindre fejl . Et af de første kompilerede imperative sprog med affaldsindsamling var Oberon , som demonstrerede anvendeligheden og ret høj effektivitet af denne mekanisme for denne type sprog, men Java -sproget bragte bred popularitet og popularitet til denne tilgang . Efterfølgende blev Java-tilgangen gentaget i .NET -miljøet og på næsten alle de sprog, der arbejdede i det, startende med C # og Visual Basic .NET . Samtidig dukkede der mange fortolkede sprog op (JavaScript, Python, Ruby, Lua), hvor affaldsindsamling blev inkluderet af hensyn til sproglig tilgængelighed for ikke-programmører og forenkling af kodning. Stigningen i hardwarekraft, der skete samtidig med forbedringen af selve samlerne, førte til, at den ekstra overhead til affaldsindsamling holdt op med at være betydelig. De fleste moderne affaldsindsamlede imperative sprog har overhovedet ingen mulighed for eksplicit manuelt at slette objekter (såsom sletoperatoren). I systemer, der bruger en fortolker eller kompilerer til bytekode, er garbage collector en del af runtime; på de samme sprog, der kompilerer til processorobjektkode, er den implementeret som et påkrævet systembibliotek.
Der er også et lille antal sprog ( nim , Modula-3 , D ), der understøtter både manuel og automatisk hukommelseshåndtering, hvortil applikationen bruger to separate dynger.