Garbage collection: differenze tra le versioni

Contenuto cancellato Contenuto aggiunto
Zorro55 (discussione | contributi)
Correzioni SOS in corso.
Zorro55 (discussione | contributi)
Correzioni SOS eseguite. Ritengo che ci sia un problema di chiarezza nell'esposizione della voce. Per non esperti molti passi sono incomprensibili.
Riga 95:
 
==== Movimento contro non movimento ====
Una volta che il set è stato classificato irraggiungibile, il Garbage Collector può semplicemente rilasciare gli oggetti irraggiungibili, oppure copiare alcuni o tutti gli oggetti raggiungibili in una nuova area di memoria, aggiornando tutti i riferimenti a tali oggetti come necessario. Questi sono chiamati rispettivamente collettor in '''''non movimento''''' ed '''''in movimento'''''.
 
A prima vista una strategia di Garbage Collector in movimento può sembrare inefficiente e costosa rispetto all'approccio di ''non movimento'', dato che sembra essere richiesto molto più lavorotempo di elaborazione per ogni ciclo. In realtà, la strategia in movimento porta a diversi vantaggi in termini di prestazioni, sia durante il ciclo di raccolta dei rifiuti, che durante l'esecuzione del programma vero e proprio:
 
* Non è necessario ulteriore lavorotempo macchina per recuperare lo spazio liberato dagli oggetti irraggiungibili, l'intera regione viene così considerata libera. Viceversa un Garbage Collector in ''non movimento'' deve controllare ogni oggetto irraggiungibile e registrare che la memoria da essi occupata sia disponibile.
* Dal momento che grandi regioni contigue della memoria sono generalmente messe a disposizione dalla strategia di ''Garbage Collector in movimento'', i nuovi oggetti possono essere attribuiti semplicemente incrementando una locazione di memoria. Una strategia di non movimento invece può, dopo qualche tempo, portare ad ununa struttura dei dati ([[heap|heap)]] fortemente frammentatoframmentata, struttura che richiede una consultazione più frequente dei piccoli blocchi di memoria disponibili, al fine di allocare questi nuovi oggetti.
* Oggetti che fanno riferimento l'uno all'altro spesso possono essere spostati in locazioni di memoria adiacenti, aumentando la probabilità che questi si trovino sulla stessa linea della [[cache]] o della pagina di [[RAM|memoria virtuale]]. Questo accelererà notevolmente l'accesso ai nuovi oggetti attraverso i riferimenti.
 
Uno svantaggio del ''Garbage Collection in movimento'' è che consente l'accesso solo attraverso i riferimenti gestiti dai riferimenti dei rifiuti, impedendo l'[[aritmetica dei puntatori]]. Ciò accade perché i puntatori iniziali non sono più validi dal momento in cui il Garbage Collector sposta l'oggetto, diventeranno puntatori sospesi. Per l'[[Interoperabilità|interaoperabilità]] con il [[codice nativo]], il Garbage Collector deve copiare la posizione dei contenuti dell'oggetto al di fuori della regione di memoria che contiene i rifiuti. Un approccio alternativo consiste nel salvare l'oggetto in memoria con un codice pin, impedendo al Garbage Collector di muoversi, consentendo ai puntatori nativi di lavorare direttamente con la memoria ed eventualmente consentendo l'aritmetica dei puntatori.<ref>{{Cita web
|url = https://msdn.microsoft.com/en-us/library/23acw07k.aspx
|titolo = Copying and Pinning
Riga 113:
}}</ref>
 
==== CopyingLa vs.copia mark-and-sweep vs.contro la copia mark-and-don't-sweep ====
PerCome abbiamo già visto, per raffinare ulteriormente la distinzione, i collettor possono tracciare gli oggetti secondo tre set (bianco, grigio e nero) e mantenerli durante il ciclo di raccolta. L'approccio più semplice è stato inventato nel 1969 e prende il nome di '''semi-space collector.''' In questo schema di Garbage Collector in movimento, la memoria è divisa in due parti: "''dallo spazio" e "allo spazio"''. Inizialmente gli oggetti sono assegnati ''"allo spazio"'' fino a quando non diventeranno oggetti a pieno titolo e la collezione attivata. All'inizio lo stato "allo spazio" diventa "dallo spazio" e viceversa, e gli oggetti raggiungibili dalla radice vengono copiati dallo spazio allo spazio. Questi oggetti vengono scansionati a turno e tutti gli oggetti a cui puntano vengono copiati allo spazio fino a quando tutti gli oggetti raggiungibili sono stati copiati in questa parte. Questo approccio ha il vantaggio di essere semplice concettualmente (i tre set sono costruiti durante il processo di copia), ma uno svantaggio è che ad ogni ciclo di raccolta viene richiesta una grande regione contigua di memoria libera. La tecnica è conosciuta anche come stop-and-copy. Un ulteriore miglioramento rispetto al semi-space collector è ''l'<nowiki/>'''algoritmo di Cheney'''.''<ref>{{Cita web|url=http://pages.di.unipi.it/ferrari/CORSI/PR2/LEZIONI2014/PR2GC.pdf|titolo=Algoritmo di Chaney}}</ref>
 
Un '''mark-and-sweep''' garbage collection, mantiene uno o due bit per ogni oggetto da registrare. L'albero di riferimento viene attraversato nel corso di un ciclo di raccolta (fase di mark) e gli oggetti vengono manipolati dal collettor per riflettere lo stato attuale e la fase di sweep libera la memoria. Il mark-and-sweep ha il vantaggio che, una volta determinato il set irraggiungibile, non può essere attuata né una strategia di movimento, né una strategia di non movimento.
Riga 121:
 
==== Generational Garbage Collector (Ephemeral Garbage Collector) ====
È stato osservato che in molti programmi gli oggetti più recenti, sono anche quelli con più probabilità di diventare rapidamente irraggiungibili ( effetto<ref>Effetto noto come Ephemeral o Generational Garbage Collection).</ref>. L'ipotesi generazionale divide gli oggetti in generazioni. Inoltre il sistema di [[Run-time|runtime]] mantiene la conoscenza di tutti i riferimenti tenendo traccia dalla loro creazione, alla sovrascrittura dei riferimenti. Quando il Garbage Collector va in esecuzione, può essere in grado di utilizzare tale conoscenza per dimostrare che alcuni oggetti inizialmente nel set iniziale bianco non sono raggiungibili senza dover attraversare l'intera struttura di riferimento. Al fine di attuare questo concetto, molti Garbage Collector generazionali utilizzano aree di memoria separate per i diversi livelli degli oggetti. Quando una regione è piena, i pochi oggetti referenziati nella vecchia memoria sono promossi (copiati) nella regione immediatamente successiva per cui l'intera regione può essere sovrascritta con nuovi oggetti. Questa tecnica permette di incrementare la velocità, in quanto la raccolta dei rifiuti di una sola regione avviene nello stesso momento.
 
Generational Garbage collection è un approccio [[Algoritmo euristico|euristico]] e alcuni oggetti irraggiungibili non possono essere recuperati ad ogni ciclo. Talvolta può quindi essere necessario recuperare tutto lo spazio disponibile. In effetti, i sistemi di runtime per i moderni linguaggi di programmazione (come [[java (linguaggio di programmazione)|java]]) di solito usano alcune varianti delle diverse strategie che sono state descritte sino ad ora.
 
==== Stop-the-world vs.contro incremental vs.contro concurrent ====
Il meccanismo '''stop-the-world''' opera semplicemente interrompendo l'esecuzione del ciclo di raccolta in modo da garantire che i nuovi oggetti non siano assegnati e non diventino improvvisamente irraggiungibili mentre il collector è in esecuzione. Svantaggio evidente è che il programma non può svolgere alcun lavoro utile mentre è in esecuzione il ciclo di raccolta (detta "embarrassing pause"). Incremental and concurrent garbage collection sono progettati per ridurre questa interruzione, svolgendo il ciclo di raccolta rifiuti in fasi distinte rispetto all'esecuzione del programma. L'idea di progettazione è quella di garantire che il programma non interferisca con il Garbage Collector e viceversa.
Incremental and concurrent garbage collection sono progettati per ridurre questa interruzione, svolgendo il ciclo di raccolta rifiuti in fasi distinte rispetto all'esecuzione del programma. L'idea di progettazione è quella di garantire che il programma non interferisca con il GC e viceversa.
 
==== Precise vs.contro conservative and internal pointers ====
Alcuni collezionisti in esecuzioni in particolari ambienti possono identificare correttamente tutti i puntatori (riferimenti) di un oggetto che sono perciò detti 'precisi', contrariamente ai collezionisti conservatori. Questi ultimi suppongono che una qualsiasi sequenza di bit in memoria potrebbe essere un puntatore che punta un qualsiasi oggetto allocato. Un esempio in cui il GCGarbage Collector conservatore è necessario è il [[linguaggio di programmazione C]] che alloca i puntatori (non void) applica un cast di tipo ([[Void (informatica)|void]]) e viceversa.
 
Una problematica correlata è quella didegli ''internal pointers'' o ''puntatori a campi'' all'interno di un oggetto. Se la [[semantica]] di un linguaggio permette puntatori interni e quindi civi possono essere molti indirizzi che si riferiscono allo stesso oggetto, si rende difficile determinare quando un oggetto è o meno rifiuto. Un esempio è il [[cC++]], in cui l'ereditarietà multipla può causare che puntatori che si riferiscono ad oggetti di base con indirizzi diversi. Anche in linguaggi come java[[Java (linguaggio di programmazione)|Java]], tuttavia, i puntatori interni possono durante il calcolo, per esempio nel riferirsi ad un array, riscontrare problemi e in un programma ben ottimizzato il puntatore corrispondente all'oggetto stesso potrebbe essere stato sovrascritto nel suo registro, in tal modo i puntatori interni hanno bisogno di essere sottoposti a scansione.
 
=== Implicazioni ===
TracingI ''tracing garbage collection'' richiedono talvolta [[overhead]] impliciti chea possono esserevolte indipendenti dalla volontà del programmatore, e può a volte portareportando a problemi di prestazioni. Per esempio i ''stop-the-world garbage collection'' durante le pause di esecuzione del programma, effettuano arbitrariamente raccolta di rifiuti, ciò è inadeguato per alcuni [[sistemi embedded]] ad alte prestazioni, per [[server]] e altre applicazioni con esigenze realtime[[real-time]]. Le differenze principali tra allocazioni manuale e automatiche consistono in:
Le differenze principali tra allocazioni manuale e automatiche consistono in:
 
'''Allocazione heap manuale''':
 
* Ricerca di blocchi di dimensioni sufficienti secondo il [[Gestore della memoria|best/first-fit]].
* Manutenzione delle [[Lista Libera|free list]].
 
'''Allocazione Garbage collection'''
 
* Individuare gli oggetti raggiungibili
* Copiare gli oggetti che sono stati spostati
* Lettura/scrittura delle barriere
* Ricerca di [[Gestore della memoria|best/ first-block]]
 
È difficile stabilire quale dei due casi sia migliore, in quanto il loro comportamento dipende dalla situazione. Alcuni progressi nel Garbage Collecotr, possono essere intesi come una migliore reazione a problemi di prestazioni. I primi sono stati Garbage Collector di tipo ''stop-the-world'', ma le loro prestazioni sono state sviate in applicazioni interattive. Tecniche di Generational collection sono utilizzati sia con ''stop-the-world'' che ''incremental collection'' per aumentarne le prestazioni.
Alcuni progressi nel GC possono essere intesi come una migliore reazione a problemi di prestazioni. I primi sono stati GC di tipo stop-the-world ma le loro prestazioni sono state sviate in applicazioni interattive. Tecniche di Generational collection sono utilizzati sia con stop-the-world che incremental collection per aumentarne le prestazioni.
 
=== Determinismo ===
Il Tracing garbage collection non è deterministico. Un oggetto che diventa ammissibile per il GCGarbage Collector sarà generalmente eliminato alla fine, ma non vi è alcuna garanzia di quando e se ciò accadrà. Questo può portare problemi:
Questo può portare problemi:
 
* La maggior parte degli ambienti con l'analisi GCGarbage Collector richiedono deallocazione manuale per non limitate risorse di memoria, che vengono eseguite in tempi non adatti.
* L'impatto sulle prestazioni causate dal GCGarbage Collector è apparentemente casuale e difficile da prevedere.
 
== Reference counting ==
 
Il Reference counting, o (conteggio dei riferimenti), è una forma di gestione automatica della memoria, dove ogni oggetto ha un conteggio del numero di riferimenti ad esso. Il contatore è incrementato quando viene creato un riferimento ad essoall'oggetto e diminuisce quando un riferimento viene distrutto. La memoria dell'oggetto viene recuperata quando il conteggio si azzera.
 
Ci sono due principali svantaggi per il conteggio dei riferimenti:
 
* Se due o più oggetti rimandano l'uno all'altro, possono creare un ciclo in cui non vengono mai rilasciati ed il loro riferimento viene valutato zero. Alcuni sistemi di GCGarbage Collector, (come quello in [[CPython]], utilizzano uno specifico conteggio dei riferimenti per affrontare questo problema).<ref>{{Cita web|url=http://www.python.org/doc/2.5.2/ext/refcounts.html|accesso=13 novembre 2008|data=21 febbraio 2008|titolo=Reference Counts|sito=Extending and Embedding the Python Interpreter|citazione=While Python uses the traditional reference counting implementation, it also offers a cycle detector that works to detect reference cycles.}}</ref>
* Nelle implementazioni più semplici, ogni assegnazione di riferimento, ed ogni riferimento perso, richiedono spesso modifiche di uno o più contatori di riferimento. Quando viene utilizzato in un ambiente [[multithreading]] tali modifiche, (di incremento/decremento), possono essere intrecciate, ma tale operazione risulta costosa per processi senza operazioni atomiche, come [[Compare-and-swap]]. Un importante vantaggio del contatore dei riferimenti è che esso fornisce un Garbage Collector deterministico.
 
Un importante vantaggio del contatore dei riferimenti è che esso fornisce un GC deterministico.
 
== Escape Analisys ==
La Escape Analisys può essere utilizzata per spostare le locazioni di memoria dallo heap allo stack o ai registri della CPU, riducendo così la quantità di lavoro che deve essere svolta dal garbage collector. Lo spostamento è lecito quando il riferimento all'oggetto non sopravvive alla subroutine in cui è stato dichiarato, cioè quando il riferimento è a tutti gli effetti una variabile locale, che non viene passata ad ulteriori subroutine o ritornata a monte.
Lo spostamento è lecito quando il riferimento all'oggetto non sopravvive alla subroutine in cui è stato dichiarato, cioè quando il riferimento è a tutti gli effetti una variabile locale, che non viene passata ad ulteriori subroutine o ritornata a monte.
==Esempio (Java)==
<source lang="java">
Line 200 ⟶ 193:
 
== Disponibilità ==
In generale, [[linguaggio di programmazione ad alto livello|linguaggi di programmazione ad alto livello]] dispongono solitamente del GCGarbag Collector come caratteristica standard. In linguaggi che non hanno ilne GCsono incorporatoprii, spesso questo viene aggiunto tramite una libreria, come con il Garbage Collection Boehm del [[C (linguaggio)|C]] e [[C++]]. La maggior parte dei [[programmazione funzionale|linguaggi di programmazione funzionali]] come la [[standard ML|ML]], [[Haskell (linguaggio)|Haskell]] e [[APL]] hanno il GCGarbage Collector come caratteristica di default. Il [[Lisp]] è stato il primo linguaggio funzionale che ha introdotto questo meccanismo.
 
Altri linguaggi dinamici come [[Ruby]] tendono ad usare il GCGarbage Collector. I [[Object oriented|linguaggi di programmazione orientati agli oggetti]], come [[Smalltalk]], [[Java (linguaggio di programmazione)|Java]] e [[ECMAScript]], solitamente prevedono il GCGarbage Collector integrato. Storicamente i linguaggi destinati ai principianti come [[BASIC]] utilitizzano spesso variabili di diversa lunghezza come stringhe e liste, in modo da sollevare il programmatore dall'onere di gestire manualmente la memoria. Il problema relativo alla velocità del sistema rallentato dall'azione del GCGarbage Collector aumenta notevolmente nei microcomputer.
 
== Ambienti limitati ==
Il GCGarbage Collector è raramente usato in ambienti di tipo embedded o real-time a causa dell'esigenze di tali ambienti. Tuttavia, sono stati sviluppati GCGarbage Collector compatibili per questi ambienti limitati<ref>
Wei Fu and Carl Hauser, "A Real-Time Garbage Collection Framework for Embedded Systems". ACM SCOPES '05, 2005.
http://portal.acm.org/ft_gateway.cfm?id=1140392&type=pdf&coll=GUIDE&dl=GUIDE&CFID=15151515&CFTOKEN=6184618
</ref>. Microsoft[[Microsoft .NET|.NET Micro Framework]] e [[J2ME|Java Platform, Micro Edition]] sono piattaforme di software embedded che dispongono di Garbage collectionCollection.
 
== Note ==