7

Alcune lingue più recenti stanno implementando ARC nei loro compilatori (Swift e Rust, per nominare una coppia). Da quello che ho capito, ciò ha ottenuto lo stesso risultato del GC di runtime (sottraendo il compito del deallocazione manuale al programmatore), pur essendo significativamente più efficiente.Qual è il vantaggio del GC di runtime su ARC in fase di compilazione?

Capisco che l'ARC potrebbe diventare un processo complesso, ma con la complessità dei moderni garbage collector sembra che non sarebbe più complesso implementare ARC. Tuttavia, ci sono ancora tonnellate di linguaggi e framework che utilizzano GC per la gestione della memoria, e anche la lingua Go, che si rivolge alla programmazione dei sistemi, utilizza GC.

Non riesco davvero a capire perché GC sarebbe preferibile ad ARC. Mi sto perdendo qualcosa qui?

risposta

20

C'è un sacco di compromessi coinvolti qui, è un argomento complesso. Ecco i grandi però:

pro GC:

  • Tracciare munnizzari può gestire i cicli di oggetti grafici. Il conteggio automatico dei riferimenti perderà memoria a meno che i cicli non vengano interrotti manualmente rimuovendo un riferimento o individuando quale lato del grafico dovrebbe essere debole. Questo è un problema abbastanza comune nella pratica nelle app conteggiate di riferimento.
  • Tracciare i garbage collector può essere in realtà moderatamente più veloce (in termini di velocità effettiva) rispetto al conteggio dei riferimenti, eseguendo il lavoro contemporaneamente, aumentando il carico di lavoro, differendo il lavoro e non rovinando le cache toccando i conteggi di riferimento nei loop caldi.
  • collettori copia può compattare il mucchio, recuperando pagine frammentate per ridurre l'impronta

pro ARC:

  • Poiché distruzione dell'oggetto avviene immediatamente quando il conteggio di riferimento colpisce 0, vite oggetto possono essere utilizzati per gestire risorse non di memoria. Con la raccolta dei rifiuti, le vite non sono deterministiche, quindi non è sicuro.
  • lavoro di raccolta è in genere più estesa, con conseguente pause molto più brevi (è ancora possibile ottenere una pausa se rilasciare una grande sottografo di oggetti)
  • perché la memoria è raccolto in modo sincrono, non è possibile "correre più veloce del collettore "allocando più velocemente di quanto possa pulire. Questo è particolarmente importante quando entra in gioco il VM paging, poiché ci sono casi degenerati in cui il thread GC colpisce una pagina che è stata sfogliata e si trova molto indietro.
  • In una nota correlata, tracciando netturbini devono camminare l'intero grafo di oggetti, che costringe inutili pagina-in (ci sono attenuanti per questo come https://people.cs.umass.edu/~emery/pubs/f034-hertz.pdf, ma non sono diffusa)
  • Tracing netturbini in genere bisogno più "spazio zero" di conteggio dei riferimenti se vogliono colpire il loro pieno rendimento

la mia opinione personale su questo è che gli unici due punti che contano davvero maggior parte dei casi sono:

  • ARC non raccogliere cicli
  • GC non ha vite deterministici

sento che entrambi questi problemi sono interruttori affare, ma in assenza di un'idea migliore, devi solo scegliere quale il problema orribile ti suona peggio.

+1

Per un confronto concettuale generale del tracciamento GC rispetto al conteggio dei riferimenti, questo documento, "Una teoria unificata della raccolta dei rifiuti", mostra come possono essere visti come doppi rigorosi l'uno dell'altro. Varie ottimizzazioni e ritocchi per ciascun approccio ti portano semplicemente lungo uno spettro che li collega: https://www.cs.virginia.edu/~cs415/reading/bacon-garbage.pdf – algal

+0

oh, sì, adoro quel foglio: D grazie per averlo collegato –