Garbage Collection ad alte prestazioni

1

Sono nuovo nella raccolta dei rifiuti ma mi sono guardato intorno. Ho notato che Reference Counting ha una pessima reputazione (PHP, Python), oltre a Conservative GC (Ruby) in determinate condizioni. Tuttavia, ho visto anche articoli che descrivono Fast GC conservativo e Conteggio dei riferimenti rapidi . Mi chiedo se ai giorni nostri esistono standard per la raccolta dei rifiuti ad alte prestazioni (oltre a non farlo affatto).

    
posta Lance Pollard 10.07.2018 - 18:32
fonte

2 risposte

5

Diversi algoritmi GC hanno diversi compromessi. Alcuni ottimizzano per un throughput elevato, altri per bassa latenza. Non esiste un singolo algoritmo migliore, quindi le piattaforme come la JVM Hotspot sono molto sintonizzabili e consentono di selezionare un profilo che si adatta al carico di lavoro previsto. Un buon algoritmo GC proverà ad auto-sintonizzarsi sul carico di lavoro effettivo, ma ovviamente ciò si ripaga solo per processi di lunga durata. Gli algoritmi GC moderni spesso funzionano anche in un thread separato per ridurre al minimo le pause, ma ciò comporta un sovraccarico della CPU più elevato.

Il conteggio dei conti non è una soluzione particolarmente interessante quando guardiamo i numeri. È a bassa velocità, ha tempi di pausa illimitati e ha un sovraccarico di memoria per oggetto gestito. Ma a differenza dei normali algoritmi GC, consente la distruzione deterministica (ad esempio modelli come RAII in C ++). Ciò lo rende interessante quando vogliamo anche gestire risorse non di memoria come gli handle di file, senza doverli chiudere esplicitamente o dover utilizzare una sintassi speciale come using (C #), try-with-resource (Java), o with (Python). È anche facile adattarsi retroattivamente a un sistema esistente, specialmente quando si vuole mescolare un non gestito con la memoria gestita. Pertanto, Objective-C (qualsiasi oggetto), C ++ ( std::shared_ptr ) e Rust ( Rc , Arc ) consentono di (esplicitamente) opt-in per il conteggio. Il conteggio manuale è un modello comune nelle API C. Quindi è uno schema meraviglioso che non sarà spostato da altri algoritmi, ma le sue prestazioni non sono competitive con il GC più avanzato.

Il documento che hai citato mostra che RC può essere competitivo nel tracciare GC, ma sembra che non stiano usando la distruzione deterministica. In base a questo vincolo rilassato e con il supporto di un runtime JVM, sono in grado di ottenere significative ottimizzazioni. Questo è inapplicabile nella maggior parte degli scenari in cui RC è attualmente in uso.

    
risposta data 10.07.2018 - 19:55
fonte
2

Gran parte della domanda dipende da cosa intendi per "prestazioni elevate". Come osserva Amon, ci sono vari approcci con diversi costi e benefici. Un sacco di motivi per cui la gente pensa che GC sia lento o comunque problematico ha a che fare con l'utilizzo, ad esempio, di una configurazione ottimizzata per il throughput quando è richiesta una bassa latenza.

Un approccio comune è quello di utilizzare i collezionisti generazionali che utilizzano algoritmi diversi in diverse generazioni. Hotspot (escluso G1) utilizza un copy-collector per la nuova generazione. I collezionisti di copie sono estremamente veloci nel collezionare oggetti morti ma sono inefficienti in termini di memoria. Ad esempio, il mio team ha un server di caching con una giovane generazione estremamente grande. Ciò consente raccolte di più GB di oggetti morti in una frazione di secondo. Nel corso dei mesi, il tempo di pausa totale per GC è inferiore a mezzo minuto circa. In termini di velocità, si tratta di prestazioni piuttosto elevate, ma per fare in modo che ciò accada, abbiamo bisogno di quasi il doppio della memoria rispetto all'heap disponibile. In termini di memoria, le prestazioni sono piuttosto basse.

Consiglio vivamente di guardare (e rivedere) questa presentazione se vuoi capire le basi della raccolta dei rifiuti. Scommetterei che Gil Tene ne sa più di chiunque altro sulla terra, se non di più.

    
risposta data 10.07.2018 - 21:57
fonte

Leggi altre domande sui tag