2015-02-04 12 views
6

Sono confuso poiché la mia applicazione perde memoria. È un server TCP che elabora centinaia di migliaia di pacchetti al minuto. Ho controllato il codice, l'ho migliorato e profilato la memoria.node.js v8 la raccolta di dati inutili non sembra attivare

Tutto sembra a posto, testare localmente con poco traffico in realtà mostra che gc rilascia correttamente la memoria. Ma quando sul server di traffico pesante dal vivo non è così.

Quindi, ho provato a utilizzare l'opzione expose-gc e ho aggiunto il gc forzato a ogni disconnessione e ora ho scoperto che la memoria non perde più o che è uscita ogni perdita?

Quindi, la mia conclusione è che il GC non si è attivato. Il mio server ha 3 GB di memoria e l'applicazione in poche ore arriva a mangiare 2,8 GB di quello.

Ora con il gc forzato l'applicazione non perde più. Mantiene circa 200 MB di memoria.

Quindi, la mia domanda, perché non è stato attivato il gc?

+0

Hai mai trovato una soluzione? Sto avendo lo stesso problema T_T –

+1

@MarsZhu scusate, ho rinunciato a Node, e ho usato Go invece, la migliore decisione di sempre. – majidarif

risposta

1

Source: StrongLoop Blog

La garbage collection fondamentale problema risolve è quello di individuare morti regioni di memoria (gli oggetti non raggiungibili/rifiuti) che non sono raggiungibili attraverso qualche catena di puntatori da un oggetto che è in diretta. Una volta identificato, queste regioni possono essere riutilizzati per nuove assegnazioni o rilasciati indietro al sistema operativo

La fuoriuscita di memoria quando utilizza ascoltatori di eventi è abbastanza comune ed è causata da una situazione in cui l'oggetto che è l'ascolto è impedito dall'essere garbage collection perché l'emettitore di eventi, anche un oggetto, sta mantenendo un riferimento ad esso.

Quindi nel codice il metodo onSuccess sarà referenziato dall'oggetto di richiesta. Tuttavia, che onSuccess è una sola funzione che viene riutilizzata come listener per tutti gli oggetti richiesta, in modo che non si verifichi l'accumulo di memoria.

Per trovare la vera causa degli oggetti lasciati in vita nel codice, controllerei la fine della connessione e assicurarmi che nessun puntatore sia rimasto in vita. Inoltre, in alcuni casi V8 non creerà un'istanza di una funzione ogni volta che viene utilizzata, e questo potrebbe essere il caso. Se entrambi vengono combinati, la memoria allocata manterrà le istanze di imputazione del callback.

oggetti che sono sopravvissuti due garbage collection minori sono promossi al “vecchio-spazio.” Old-spazio è garbage collection in piena GC (importante ciclo di raccolta dei rifiuti ), che è molto meno frequente. Presumo che questo sia stato recuperato, ma l'opzione di allocare più velocemente dei cicli di spostamento potrebbe essere considerata, e quindi quando si attiva manualmente la raccolta di dati inutili , viene avviato un ciclo di GC completo.

Per assicurare allocazione veloce oggetto, pause di raccolta rifiuti breve, e la “memoria frammentazione V8” impiega uno stop-mondo, generazionale, preciso, spazzino. V8 interrompe essenzialmente l'esecuzione del programma durante l'esecuzione di un ciclo di garbage collection completo.

Questo può spiegare perché la memoria non perde quando V8 viene forzato nella pulizia dei rifiuti.

+2

Questo è confuso per non parlare di prendere paragrafi esatti dal blog [strongloops] (http://strongloop.com/strongblog/node-js-performance-garbage-collection/). – majidarif

+0

Vero, mi scuso per non aver aggiunto la fonte. Di solito lo faccio. – Selfish

+0

Solo l'ultimo paragrafo di questa risposta è pertinente alla domanda! "Gli oggetti che sono sopravvissuti a due raccolte di garbage minori sono promossi a" vecchio spazio ". Il vecchio spazio è spazzatura raccolta in GC completo (ciclo di raccolta dei rifiuti maggiore), che è molto meno frequente. Suppongo che questo sia molto estrapolato, ma l'opzione l'allocazione più rapida dei cicli di spazzamento potrebbe essere presa in considerazione e, pertanto, quando si attiva manualmente la procedura di Garbage Collection, viene attivato un ciclo di GC completo. " –

0

Sto notando lo stesso problema con la garbage collection che non si verificava. Il test del mio server che spegne lo stesso contenuto (reso reagire) ripetutamente in una memoria di script di test si esaurirebbe in un'ora o giù di lì. Questa istanza AWS ha solo 1 GB di RAM.

Dopo aver forzato la garbage collection ogni volta che heapUsed ha superato 256 MB, tutto funziona bene per ore e ore. heapUsed oscilla da circa 150 MB dopo un GC a poco più di 256 MB.

Nel frattempo heapTotal alla fine si stabilizza a circa 340 MB.

La mia conclusione è che il mio server non perde memoria, la garbage collection non sta accadendo come previsto.

Ecco quello che faccio:

setInterval (function() { 
    let mu = process.memoryUsage(); 
    console.log('heapTotal:', mu.heapTotal, 'heapUsed:', mu.heapUsed); 
    if (mu.heapUsed > 256 * 1024 * 1024) { 
     console.log('Taking out the garbage'); 
     global.gc(); 
    } 
}, 1000 * 60); 

forse sarebbe meglio controllare la memoria dopo ogni richiesta.

Problemi correlati