nodejs node nexttick loop guide event javascript node.js memory-leaks infinite-loop v8

javascript - nexttick - server on node js



Consumo de memoria de NodeJS en un ciclo infinito (3)

Está bloqueando el bucle de evento node.js al no volver nunca a él.

Cuando escribe algo en un nodo de flujo, lo hace de forma asíncrona: envía la solicitud de escritura, pone en cola la información sobre la solicitud enviada en las estructuras de datos internas de la secuencia y espera la devolución de llamada que notificará sobre la finalización.

Si está bloqueando un bucle de evento, nunca se invocará la devolución de llamada (porque los eventos entrantes nunca se procesan) y las estructuras de datos auxiliares puestas en la cola nunca se liberarán.

Lo mismo puede suceder si "sobrecarga" un evento de bucle al programar constantemente sus propios eventos con nextTick / setInterval / setTimeout.

No sé si esto es un error con Node o V8, pero si ejecuto el siguiente código, el proceso del nodo pierde memoria. El GC nunca parece funcionar y en unos pocos segundos consume más de 1GB de memoria. Este es un comportamiento inesperado. ¿Me estoy perdiendo de algo?

Aquí está el código:

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

Obviamente, esta es una situación un tanto artificial, pero puedo ver un problema con un proceso de larga duración que nunca liberaría la memoria.

Edición: Intenté tanto con v0.5.10 (inestable) como con v0.4.12 (estable) y la versión inestable funciona un poco mejor --- la versión estable simplemente deja de enviar a la consola pero continúa consumiendo memoria, mientras que la versión estable continúa ejecutando y consumiendo memoria sin pausa.


La respuesta de @VyacheslavEgorov parece estar bien, pero supongo que aplazar el ciclo del evento resolvería el problema. Es posible que desee comparar cómo su infinito for-loop compara con esta estrategia infinita de bucle:

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

La idea es usar process.nextTick(cb) para diferir al bucle de evento y (presumiblemente) permitir que el GC haga su trabajo.


Como se ha liberado Node.js v0.10, setImmediate debe usarse como la primera opción en lugar de process.nextTick cuando se llama a la devolución de llamada recursiva.

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

El consumo de memoria de este fragmento de código se mantuvo bajo (<10MB) después de ejecutarse durante aproximadamente 15 minutos en mi computadora.

Por el contrario, Ejecutar el infinito for loop causó la pérdida de memoria y el process.nextTick arrojó un error de Maximum call stack size exceeded .

Consulte también esta sección de preguntas y respuestas: setImmediate vs. nextTick