Nici unul nu este destul de complicat de program modern, nu este lipsit de colectare a gunoiului, manual sau automat. Nu e nimic de făcut - memoria rămâne încă o resursă valoroasă și nu putem să-l elibereze pe cât posibil. Care sunt abordările existente de colectare a gunoiului?
Manual de management al memoriei
Manual de gestionare a memoriei este simplu de scandalos. Atunci când aplicația are nevoie ca de memorie, acesta spune malloc sau noi, iar atunci când memoria nu mai este nevoie - gratuit sau șterge. Viața este frumoasă și uimitoare, problema este închis ... sau nu?
În practică, se dovedește că atribuirea responsabilității pentru gestionarea memoriei pentru un programator de multe ori duce la o scurgere de memorie erori și referințe dangling. Nu vorbesc despre astfel de fleacuri care acceptă codul devine mai complicată decât în cazul utilizării de management automat al memoriei.
Cu toate acestea, managementul memoriei manual este încă utilizat pe scară largă în C, C ++ și alte limbi. cel puțin pentru motivul că nu orice problemă ne putem permite să folosească colectorul de gunoi de la. Ca un exemplu de astfel de probleme vin în minte pentru a dezvolta drivere, compilatoare, codec-uri / arhivator, solicitante aplicații server de performanță și jocuri tridimensionale pe calculator.
managementul memoriei manuală necesită programator într-o anumită disciplină. Dacă este posibil, este de dorit să se pună date pe stivă. Dacă datele trebuie să fie stocate într-o grămadă, este de dorit să elibereze memoria alocată în aceeași procedură și aceeași metodă, unde a fost izolat. În cazul în care puteți face fără utilizarea de link-uri, datele ar trebui să fie stocate de valoare. Și așa mai departe.
contoare de referință
Cel mai simplu mecanism de gestionare automată a memoriei este de a utiliza numărul de referință. Ideea este după cum urmează. Pe lângă datele din locația de memorie selectată este stocată ca un număr de referință pentru datele. contorul este incrementat și distrugerea de a crea un nou indice - a scăzut. În cazul în care, după o reducere a numărului de unități a devenit zero, atunci datele suplimentare care nu este utilizat de nimeni și de memorie ar trebui să fie eliberat.
Această metodă nu este aproape inferior la performanta manualul de management al memoriei, dar poate reduce semnificativ numărul de erori inerente în ea. suport cod este de asemenea simplificată. O problemă semnificativă cu această abordare constă în faptul că, în prezența unor referințe circulare, unele contoare nu dispare și fluxul de memorie departe. Pentru a combate acest lucru, utilizați indicii slabe (weakptr), care nu participă la numărare de referință.
numărul de referință utilizate destul de succes în C ++ (așa-numitele „indicii inteligente“) și Perl.
Calc colector de gunoi
Din câte știu, astăzi nu este utilizat în urmărirea forma colector de gunoi pur oriunde. In cele mai multe limbi cu managementul automat al memoriei, această metodă este aplicată cu diverse modificări, care vor fi discutate mai jos.
colector copierea
Depozitarea utilizate două grămezi. Una dintre ele este utilizată în prezent, în timp ce al doilea este rezervat pentru viitor. Noile date sunt puse în primul teanc.
Când primul gramada de funcționare din cameră, vom evita toate datele și să le copiați în a doua gramada. Atunci când aceste date sunt în mod natural compactat, și link-uri de date sunt modificate. La finalizarea gramada de by-pass inversat, al doilea buchet este activat, iar primul - rezervat.
Aici există o mulțime de avantaje față de trasor de către colectorul de gunoi. În primul rând, nu avem nevoie pentru a stoca orice informații suplimentare cu privire la toate domeniile de memorie alocate (problema destructori, finalizers temporar deoparte). În al doilea rând, din cauza compresie a datelor procesor cache și memorie este utilizat mai eficient.
Dar există, de asemenea, o serie de dezavantaje. Primul lucru pe care capturile ochi - 50% din memoria alocată cele mai multe ori nu este utilizat. Dar, pe de altă parte, ca urmare a fragmentării memoriei neutilizate poate fi mult mai mare procent, așa că, probabil, acest lucru este doar ei înșiși, și să nu vă faceți griji. Dar ceea ce este cu adevărat îngrijorător, este faptul că multe dintre datele de viață lungă va fi copiată în mod permanent de la un teanc la altul.
Ar trebui, de asemenea, să acorde o atenție la costurile generale asociate cu necesitatea de a modifica indicii. Și da, programul de la momentul colectării gunoiului încă mai trebuie să suspende.
Dacă nu mă înșel, abordarea folosind două grămezi de orice folosite sau o dată utilizate în Java.
Tracer și etanșarea gunoier
Ca urmare, datele colectate de lungă durată la începutul heap și nu se mișcă la fiecare colectare. Memoria este utilizată mai eficient decât în cazul utilizării a două grămezi. Cu toate acestea, algoritmul este complicată de colectorul de gunoi. Pentru a evita copiile de date redundante, par să necesite administrarea de mai multe optimizări, cum ar fi „nu comprima datele, în cazul în care nivelul de fragmentare în această parte a grămezii nu depășește 25%“, și așa mai departe.
Colectorul de gunoi de generații
Baza colectorului de gunoi de generații (colector de gunoi de generații), pe ideea că majoritatea obiectelor (aici, va fi convenabil să împrumute terminologia OOP) încetează să mai fie folosită la scurt timp după înființarea sa. În acest sens, toate obiectele sunt combinate în diferite generații.
Obiecte noi sunt considerate obiecte din prima generație. Dacă un astfel de obiect a intrat primul (sau, în general, N-lea) de colectare a gunoiului, acesta este plasat într-o multitudine de obiecte din a doua generație scanate mai puțin frecvent. În cazul în care obiectele din acest set se confruntă, de asemenea, o colecție de gunoi (sau mai multe ansambluri), ele sunt mutate la setul de obiecte de a treia generație, chiar mai rar verificate, și așa mai departe.
De obicei, atunci când traversează graficul obiect este simplu - dacă ne-am întâlnit obiectul unei generații mai vechi decât în prezent scanat, în această direcție vom. Cu toate acestea, există un moment delicat. Deoarece obiectele pot varia în general, acestea pot conține de asemenea referiri la obiectele generatiei tinere. Prin urmare, în timpul executării programului este necesară pentru a monitoriza situația. atunci când un obiect mai în vârstă începe să se refere la mai tineri și de a adăuga, în acest caz, un obiect tânăr în „set de rădăcină“ obiecte din generația corespunzătoare. În caz contrar, colectorul de gunoi-l șterge în mod greșit ca imposibil de găsit.
De colectare a gunoiului de generații accelerează în mod semnificativ urmărirea gunoier și, prin urmare, pe scară largă. În special, o astfel de abordare este folosită în Python.
soluții hibride
În practică, abordarea descrisă mai sus adesea combinate și modificate, rezultând, de exemplu, etanșarea de urmărire gunoier generații. În unele limbi, oferind mai multe colectoare de gunoi de a alege. De exemplu, unul dintre ele poate fi mai economică utilizare a memoriei, iar celălalt - pentru a face mai rapid de colectare a gunoiului. În cele din urmă, există, de asemenea, colectoare de gunoi paralele, dar această problemă depășește bara.