Consumo di memoria NodeJS in un ciclo infinito

Non so se questo è un bug con Node o V8, ma se eseguo il codice seguente il processo del nodo perde memoria. Il GC non sembra mai dare il via e in pochi secondi sta consumando> 1 GB di memoria. Questo è un comportamento inaspettato. Mi sto perdendo qualcosa?

Ecco il codice:

for(;;) { console.log(1+1); } 

Ovviamente, questa è una situazione un po ‘forzata, ma posso vedere un problema con un processo di lunga durata che non libererebbe mai memoria.

Edit: ho provato entrambi con v0.5.10 (unstable) e v0.4.12 (stable) e la versione unstable ha un rendimento un po ‘migliore — la versione stabile si ferma appena in uscita alla console ma continua a consumare memoria, mentre la versione stabile continua a eseguire e consumare memoria senza pause.

    Stai bloccando il ciclo degli eventi node.js non ritornando mai ad esso.

    Quando scrivi qualcosa su uno stream, node.js lo fa in modo asincrono: invia la richiesta di scrittura, accoda le informazioni sulla richiesta inviata nelle strutture dati interne del stream e attende il callback che lo notificherà in merito al completamento.

    Se si sta bloccando il loop degli eventi, il callback non verrà mai chiamato (poiché gli eventi in entrata non vengono mai elaborati) e le strutture di dati ausiliari in coda nello stream non verranno mai liberate.

    Lo stesso può accadere probabilmente se si “sovraccarichi” il ciclo degli eventi programmando costantemente i propri eventi con nextTick / setInterval / setTimeout.

    La risposta di @VyacheslavEgorov sembra giusta ma suppongo che il rinvio al ciclo degli eventi risolva il problema. Potresti voler confrontare il modo in cui il tuo for-loop infinito si confronta con questa strategia di loop infinita:

     function loginf() { console.log(1+1); process.nextTick(loginf); } loginf(); 

    L’idea è di usare process.nextTick(cb) per rimandare al ciclo degli eventi e (presumibilmente) permettere al GC di fare le sue cose.

    Dato che Node.js v0.10 è stato rilasciato, setImmediate dovrebbe essere usato come prima scelta invece di process.nextTick quando si chiama il callback ricorsivo.

     function loginf() { console.log(1+1); setImmediate(loginf); } loginf(); 

    Il consumo di memoria di questo blocco di codice è rimasto basso (<10 MB) dopo aver funzionato per circa 15 minuti sul mio computer.

    Al contrario, l’esecuzione for loop infinito for loop causava il porro della memoria e process.nextTick lanciava un errore di Maximum call stack size exceeded .

    Controlla anche questo Q & A: setImmediate vs. nextTick