Trasforma la tua domanda in giro. La vera domanda motivante è in quali circostanze possiamo evitare i costi della garbage collection?
Bene, per prima cosa, quali sono i costi della raccolta dei rifiuti? Ci sono due costi principali. Innanzitutto, devi determinare cosa è vivo ; ciò richiede potenzialmente molto lavoro. In secondo luogo, devi compattare i buchi che si formano quando liberi qualcosa che è stato allocato tra due cose che sono ancora vivi. Quei buchi sono uno spreco. Ma comprimerli è anche costoso.
Come possiamo evitare questi costi?
Chiaramente se puoi trovare uno schema di utilizzo della memoria in cui mai allocare qualcosa di longevo, quindi assegnare qualcosa di breve durata, quindi assegnare qualcosa di longevo, puoi eliminare il costo dei buchi . Se puoi garantire che per alcuni sottoinsiemi dello spazio di archiviazione, ogni allocazione successiva abbia una vita più breve rispetto a quella precedente in quella memoria, quindi non ci saranno mai buchi in quella memoria.
Ma se abbiamo risolto il problema del buco, allora abbiamo risolto anche il problema della garbage collection . Hai qualcosa in quel magazzino che è ancora vivo? Sì. Tutto è stato assegnato prima che durasse più a lungo? Sì, questa supposizione è come abbiamo eliminato la possibilità di buchi. Quindi tutto ciò che devi fare è dire "è l'allocazione più recente in vita?" e tu sai che tutto è vivo in quella memoria.
Abbiamo una serie di allocazioni di memoria in cui sappiamo che ogni allocazione successiva è più breve della precedente allocazione? Sì! I fotogrammi di attivazione dei metodi vengono sempre distrutti nell'ordine opposto in cui sono stati creati perché sono sempre più brevi dell'attivazione che li ha creati.
Quindi possiamo archiviare i frame di attivazione nello stack e sapere che non hanno mai bisogno di essere raccolti. Se c'è una cornice nella pila, l'intera serie di fotogrammi sotto di essa è più longeva, quindi non è necessario che vengano raccolti. E saranno distrutti nell'ordine opposto in cui sono stati creati. Il costo della raccolta dei rifiuti è quindi eliminato per i frame di attivazione.
Ecco perché abbiamo il pool temporaneo nello stack in primo luogo: perché è un modo semplice di implementare l'attivazione del metodo senza incorrere in una penalità di gestione della memoria.
(Ovviamente il costo della raccolta dei dati inutili che raccoglie la memoria riferita a dai riferimenti sui frame di attivazione è ancora lì.)
Consideriamo ora un sistema di controllo del flusso in cui i frame di attivazione sono non distrutti in un ordine prevedibile. Cosa succede se un'attivazione di breve durata può dare luogo a un'attivazione di lunga durata? Come puoi immaginare, in questo mondo non puoi più utilizzare lo stack per ottimizzare la necessità di raccogliere le attivazioni. Il set di attivazioni può contenere ancora dei buchi.
C # 2.0 ha questa caratteristica sotto forma di yield return
. Un metodo che restituisce un rendimento verrà riattivato in un momento successivo - la prossima volta che viene chiamato MoveNext - e quando ciò accade non è prevedibile. Pertanto, le informazioni che normalmente si trovano nello stack per il frame di attivazione del blocco iteratore vengono invece memorizzate nell'heap, dove vengono raccolte informazioni inutili quando viene raccolto l'enumeratore.
Allo stesso modo, la funzione "async / await" disponibile nelle prossime versioni di C # e VB ti consentirà di creare metodi le cui attivazioni "cedono" e "riprendono" in punti ben definiti durante l'azione del metodo. Poiché i frame di attivazione non vengono più creati e distrutti in modo prevedibile, tutte le informazioni che prima erano memorizzate nello stack dovranno essere memorizzate nell'heap.
È solo un accidente della storia che ci è capitato di decidere per alcuni decenni che le lingue con frame di attivazione creati e distrutti in modo rigorosamente ordinato fossero di moda. Poiché le lingue moderne sono sempre più carenti di questo proprietà, aspettati di vedere sempre più lingue che reificano le continuazioni sull'heap raccolto dalla spazzatura, piuttosto che sullo stack.