2014-07-18 11 views
7

penso che sono in esecuzione in una perdita di memoria con una app espresso quando si collega un numero x di EventSource client ad esso. Dopo aver collegato i client e inviato loro x messaggi e disconnettendoli, l'app Express Express rilascia solo una piccola parte dell'heap/RSS allocato.Perdita di memoria in Express.js con EventSource

Per confermare questo ho salvato un Heapdump all'avvio del server e uno dopo aver collegato 7000 client ad esso e l'invio di messaggi x a ciascun client. Ho aspettato un po 'di tempo per dare al GC la possibilità di ripulire prima di prendere l'istantanea dell'heap.

Per confrontare queste istantanee di heap, le ho caricate nella vista Profilo Strumenti di sviluppo Chrome e ho scelto la modalità "Confronto".

Le mie domande sono:

1) Come interpretare questi numeri? (per riferimento vedere il mucchio allegata un'istantanea screenshot.)

2) Per esempio Sembra che il Socket oggetti non quasi senza alcun oggetto a tutti, è corretto?

3) Potete darmi altri suggerimenti per indagare il problema?

Heap Snapshot Express.js app

+0

Se qualcuno è interessato nel codice che uso per provarlo, è qui: [Server & Codice Cliente] (https: //gist.github .com/roundrobin/a6e3d38cb24fcc112418) – BausTheBig

+0

non è una perdita di memoria, è stato aggiunto un riferimento a loro e non rimosso, non si libera la memoria mentre è ancora possibile accedervi. 'ALL_CLIENTS' sta aggiungendo roba ad esso ora che li stai chiudendo non rimossi da' ALL_CLIENTS' quindi c'è ancora un riferimento ad essi una volta che hai finito e connessione chiamata chiusa 'cancella ALL_CLIENT [chiave]' dove la chiave è Chiave del client corrente se si dispone di un riferimento non è possibile rimuovere i dati in là altri saggi potreste potenzialmente avere un riferimento ad un'altra memoria di app se saltato lì –

risposta

1

si può essere liberi da perdita di memoria e come bonus evitare il garbage collector. Tutto quello che devi fare è il polling degli oggetti.

Si potrebbe fare qualcosa di simile

var clientsPool = new Array(1000); 
var clientsConnected = []; 

Quando un nuovo client si connette, si fa

var newClient = clientsPool.pop(); 
//set your props here 
clientsConnected.push(newClient); 

Questo è un modo fantastico per evitare il Garbage Collector e prevenire perdita di memoria. Certo, c'è un po 'di lavoro in più e dovrai gestirlo con attenzione, ma vale assolutamente la pena per le prestazioni.

C'è un discorso impressionante a questo proposito, qui si va https://www.youtube.com/watch?v=RWmzxyMf2cE

+0

non rispondi a un altro membro risponde !!! –

+0

vapore come 'rubare'? Se guardi da vicino, le nostre risposte sono diverse. Fa scorrere tutti i client mentre eseguo il polling degli oggetti. Inoltre, usa la parola chiave delete che è pessima. E per riassumere ... giuro che non ho copiato! Scritto dalla mia mente, non sono un ladro = (( – Magus

+0

cosa succede se non vuoi un Pool la tua idea è fantastica se sai esattamente quante persone devono connettersi o felici di limitare le connessioni del tuo server, ma cosa succede se tu? non voglio che sia limitato? diciamo che apache ha fatto questo e che la maggior parte delle connessioni sono 1000 siti Web che potrebbero essere infastiditi dal fatto che 1 pagina potrebbe richiedere circa 10 connessioni che significherebbe che solo 100 utenti potrebbero connettersi a quel server Apache, ci sono migliori modi di usare cancellare si, ma usare un limite non è il modo di farlo ... –

1

Per quanto riguarda il mio commento ...

Javascript non può chiarire una sezione di memoria dovrebbe essere nulla che indica esso circa 2 anni fa qualcuno ha trovato un exploit ed è stato subito chiuso così e funziona così

var someData = ["THIS IS SOME DATA SAY IT WAS THE SIZE OF A SMALL APPLICATION"]; 
var somePointer = someData[0]; 
delete someData; 

hanno poi iniettato un'applicazione in somePointer come è stato un riferimento a una posizione di memoria quando non vi erano dati ora. hey presto ti ha iniettato memoria.

Quindi, se v'è un riferimento come sopra somePointer = someData[0]; non puoi liberare la memoria fino a quando non delete someData quindi è necessario rimuovere tutti i riferimenti a tutto quello che vuoi pulizia nel vostro caso ALL_CLIENTS.push(this); sulla linea 64 è fare memoria di sistema accessibile attraverso ALL_CLIENTS, così che cosa si può fare è

linea 157

_.each(ALL_CLIENTS, function(client, i) { 
        var u; // holds a undefined value (null, empty, nothing) 
        client.close(); 
        //delete ALL_CLIENTS[i]; 
        ALL_CLIENTS[i] = u; 
        ALL_CLIENTS.unused++; 
       }); 

In un'altra nota questa non è una perdita di memoria una perdita di memoria è dire aveste questo server si chiude, se la memoria non liberare dopo che si è usciti esso allora hai una perdita di memoria, se lo fa pulire la memoria dietro di sé non è una perdita è solo una cattiva gestione della memoria

Grazie a @Magus per aver sottolineato che l'eliminazione non è la cosa migliore che si possa usare, tuttavia non consiglierei mai di implementare una struttura limitante, ma si potrebbe provare

linea 27: ALL_CLIENTS.unused = 0;

linea 64:

var u; 
if(ALL_CLIENTS.unused > 0){ 
    for(var i = 0; i < ALL_CLIENTS.length; i++){ 
     if(ALL_CLIENTS[i] == u){ 
      ALL_CLIENTS[i] = this; 
      ALL_CLIENTS.unused--; 
      i = ALL_CLIENTS.length; 
     } 
    } 
}else{ 
    ALL_CLIENTS.push(this); 
} 
+0

Su questa nota che è solo la prima cosa che ho trovato in quel modo controllare il codice per più riferimenti non stai cancellando quando vuoi liberare la memoria fino a –

+0

Grazie lasciami controllare e accetto la tua risposta! – BausTheBig

+0

Per favore, non usare mai la parola chiave delete !! Fa più male che bene. Non c'è problema nel tenere un oggetto in memoria se lo riutilizzi più tardi. Mantieni tutto in memoria e utilizza gli stessi oggetti per diversi client, evitando così il tempo di allocazione, il tempo di deallocation (elimina la parola chiave rovinerà le tue prestazioni) e il tempo di raccolta dei dati inutili.Guarda il video che ho postato sulla mia risposta per maggiori informazioni, ne vale la pena – Magus