tutorial nodejs node instalar framework ejemplos documentación actualizar javascript node.js v8

javascript - nodejs - node js tutorial



recolección de basura con node.js (3)

En realidad, tu ejemplo es un tanto complicado. ¿Fue a propósito? Parece que está enmascarando la variable de val externa con un argumento de val innerofprogram () dentro del alcance léxico interno, en lugar de usarlo realmente. Pero de todos modos, estás preguntando sobre str así que déjame ignorar la dificultad de val en tu ejemplo solo por el bien de la simplicidad.

Supongo que la variable str no se recopilará antes de que termine la función restofprogram (), incluso si no la usa. Si el resto del programa () no usa str y no usa eval() y new Function() entonces se puede recopilar de forma segura, pero dudo que lo haga. Esta sería una optimización engañosa para V8 que probablemente no valga la pena. Si no hubiera eval y new Function() en el lenguaje, entonces sería mucho más fácil.

Ahora, no tiene por qué significar que nunca se recopilará porque cualquier controlador de eventos en un ciclo de eventos de subproceso único debería finalizar casi instantáneamente. De lo contrario, todo su proceso sería bloqueado y usted tendría problemas más grandes que una variable inútil en la memoria.

Ahora me pregunto si no quiso decir algo más de lo que realmente escribió en su ejemplo. Todo el programa en Node es como el navegador: simplemente registra las devoluciones de llamadas de eventos que se activan de forma asincrónica más tarde después de que el cuerpo principal del programa ya haya finalizado. Además, ninguno de los manipuladores está bloqueando, por lo que ninguna función se está demorando demasiado en terminar. No estoy seguro si entendí lo que realmente quiso decir en su pregunta, pero espero que lo que he escrito sea útil para comprender cómo funciona todo.

Actualizar:

Después de leer más información en los comentarios sobre cómo se ve tu programa, puedo decir más.

Si su programa es algo así como:

readfile("blah", function (str) { var val = getvaluefromstr(str); // do something with val Server.start(function (request) { // do something }); });

Entonces también puedes escribirlo así:

readfile("blah", function (str) { var val = getvaluefromstr(str); // do something with val Server.start(serverCallback); }); function serverCallback(request) { // do something });

Hará que str se salga del alcance después de que se llame a Server.start () y eventualmente se recolectará. Además, hará que su sangría sea más manejable, lo que no debe subestimarse para programas más complejos.

En cuanto al val , podrías convertirlo en una variable global en este caso, lo que simplificaría enormemente tu código. Por supuesto que no es necesario, puede luchar contra cierres, pero en este caso hacer val global o hacerlo vivir en un ámbito externo común tanto para la devolución de llamada readfile como para la función serverCallback parece ser la solución más directa.

Recuerde que en todas partes, cuando puede usar una función anónima, también puede usar una función con nombre, y con ellas puede elegir en qué ámbito desea que vivan.

Tenía curiosidad sobre cómo funciona el patrón node.js de funciones anidadas con el recolector de basura de v8. aquí hay un ejemplo simple

readfile("blah", function(str) { var val = getvaluefromstr(str); function restofprogram(val2) { ... } (val) })

Si el programa restof es de larga ejecución, ¿no significa eso que str nunca obtendrá basura recolectada? Según entiendo, con el nodo terminas con funciones anidadas mucho. ¿Esto se recoge basura si restofprogram fue declarado fuera, por lo str no podría estar en el alcance. ¿Es esta una práctica recomendada?

EDITAR No tenía la intención de complicar el problema. Eso fue solo descuido, así que lo modifiqué.


Mi suposición es que str no será basura recolectada porque puede ser usada por restofprogram (). Sí, y str debe recibir GCed si restofprogram fue declarado afuera, excepto, si haces algo como esto:

function restofprogram(val) { ... } readfile("blah", function(str) { var val = getvaluefromstr(str); restofprogram(val, str); });

O si getvaluefromstr se declara como algo como esto:

function getvaluefromstr(str) { return { orig: str, some_funky_stuff: 23 }; }

Pregunta de seguimiento: ¿v8 simplemente hace GC o hace una combinación de GC y ref. contando (como python?)


Respuesta simple: si el valor de str no se referencia desde ningún otro lugar (y str no se referencia desde restofprogram ) será inalcanzable tan pronto como la function (str) { ... } regrese.

Detalles: el compilador V8 distingue variables locales reales de las llamadas variables de contexto capturadas por un cierre, sombreadas por a con- declaración o una invocación de eval .

Las variables locales viven en la pila y desaparecen tan pronto como se completa la ejecución de la función.

Las variables de contexto viven en una estructura de contexto asignada en montón. Desaparecen cuando la estructura de contexto muere. Lo importante a tener en cuenta aquí es que las variables de contexto del mismo ámbito viven en la misma estructura. Déjame ilustrarlo con un código de ejemplo:

function outer () { var x; // real local variable var y; // context variable, referenced by inner1 var z; // context variable, referenced by inner2 function inner1 () { // references context use(y); } function inner2 () { // references context use(z); } function inner3 () { /* I am empty but I still capture context implicitly */ } return [inner1, inner2, inner3]; }

En este ejemplo, la variable x desaparecerá tan pronto como el outer regrese, pero las variables y y z desaparecerán solo cuando inner1 tanto inner1 , inner2 e inner3 . Esto sucede porque y y z están asignados en la misma estructura de contexto y los tres cierres hacen referencia implícita a esta estructura de contexto (incluso inner3 que no la usa explícitamente).

La situación se complica aún más cuando comienzas a usar con -statement, try / catch -statement que en V8 contiene un implícito con -statement dentro de catch clause o global eval .

function complication () { var x; // context variable function inner () { /* I am empty but I still capture context implicitly */ } try { } catch (e) { /* contains implicit with-statement */ } return inner; }

En este ejemplo, x desaparecerá solo cuando muera el inner . Porque:

  • try / catch -contiene implícito con -statement in catch clause
  • V8 asume que cualquiera con -statement sombrea a todos los lugareños

Esto fuerza a x a convertirse en una variable de contexto y el inner captura el contexto, por lo que x existe hasta que muere el inner .

En general, si quiere estar seguro de que la variable dada no retiene algún objeto por más tiempo de lo realmente necesario, puede destruir fácilmente este enlace asignando null a esa variable.