Desmitificando las Fugas de Memoria en JavaScript

This ad is not shown to multipass and full ticket holders
JSNation US
JSNation US 2025
November 17 - 20, 2025
New York, US & Online
See JS stars in the US biggest planetarium
Learn More
In partnership with Focus Reactive
Upcoming event
JSNation US 2025
JSNation US 2025
November 17 - 20, 2025. New York, US & Online
Learn more
Bookmark
Rate this content

Hoy en día es posible escribir aplicaciones complejas con solo un puñado de desarrolladores en un corto período de tiempo, confiando en Frameworks y herramientas. Pero, ¿qué sucede cuando la aplicación se bloquea con errores de falta de memoria? ¿Cómo es posible garantizar tiempos de respuesta rápidos? Estos problemas todavía se consideran difíciles de resolver.

Vamos a profundizar en los internos de Node.js y aprender sobre los perfiles y el recolector de basura. Comprender cómo funciona el sistema en profundidad te permite escribir código que es más seguro, rápido y menos propenso a errores.

Asegurémonos de que siempre brindes la mejor experiencia para todos. Tú mismo y tu cliente. Vamos a encontrar esa fuga de memoria y solucionarla.

Aprendizajes

  • Los participantes entienden el manejo de memoria de Node.js y sus deficiencias.
  • Los participantes saben cuándo perfilar su aplicación para identificar fugas de memoria y código lento.
  • Los participantes son capaces de encontrar y abordar la mayoría de las fugas de memoria.

This talk has been presented at Node Congress 2021, check out the latest edition of this JavaScript Conference.

FAQ

En JavaScript, la memoria se divide en memoria de pila y memoria de montón. La memoria de pila es manejada automáticamente por el sistema operativo, mientras que la memoria de montón, utilizada para almacenar variables dinámicamente asignadas, requiere un manejo más complejo y es donde generalmente ocurren las fugas de memoria.

Una fuga de memoria ocurre cuando un programa informático gestiona incorrectamente la memoria de acceso aleatorio, resultando en que la memoria que ya no se necesita no se libera, acumulando más memoria con el tiempo y pudiendo llevar a un bloqueo del programa.

Un volcado de memoria es un snapshot del estado de la memoria en un punto específico en el tiempo. Analizar estos volcados puede ayudar a identificar irregularidades y patrones que indican fugas de memoria, facilitando la localización del origen del problema.

Para identificar y solucionar fugas de memoria en Node.js, se pueden utilizar herramientas y flags como '--inspect' y 'trace GC'. Estas herramientas ayudan a conectar con herramientas de inspección y a monitorizar las actividades del recolector de basura, respectivamente.

Las fugas de memoria en JavaScript pueden ser causadas por múltiples factores incluyendo el uso incorrecto de tipos de datos, escuchadores de eventos no gestionados correctamente, y closures que ocultan variables al recolector de basura, entre otros.

Ruben Bridgewater
Ruben Bridgewater
33 min
24 Jun, 2021

Comments

Sign in or register to post your comment.
Video Summary and Transcription
La charla discute desmitificar las fugas de memoria en JavaScript, cubriendo temas como la asignación de memoria, fugas de memoria típicas y problemas, manejo de descriptores de archivos y oyentes de eventos, herramientas y técnicas para identificar fugas de memoria, arreglar fugas de memoria y reiniciar aplicaciones, y la experiencia personal de Ruben con las fugas de memoria.

1. Demystifying Memory Leaks in JavaScript

Short description:

Hola a todos. Mi nombre es Ruden Britschwurter. Soy miembro de NodeJS TC. Trabajo como arquitecto principal de software en MyConvolt, y estoy feliz de estar aquí hoy en la conferencia de Node. Hoy voy a hablar sobre desmitificar las fugas de memoria. Así que las fugas de memoria a menudo se consideran algo difícil y complicado de resolver. Pero, ¿es realmente así? ¿Y cómo podemos facilitar el proceso? Una fuga de memoria es cuando un programa de computadora gestiona incorrectamente la memoria de acceso aleatorio. De una manera que la memoria, que ya no se necesita, no se libera. Y la línea azul es claramente una fuga de memoria porque con el tiempo solo asignas más y más memoria sin liberarla nuevamente. Y esto es malo. Entonces, ¿cómo manejamos la memoria en JavaScript en particular? Porque no tenemos que preocuparnos por ello, ¿verdad? Todo esto se hace de manera transparente y esto es perfecto. Y la memoria simplemente se libera. ¿Por qué debería haber una fuga de memoria en primer lugar?

Hola a todos. Mi nombre es Ruden Britschwurter. Soy miembro de NodeJS TC. Trabajo como arquitecto principal de software en MyConvolt, y estoy feliz de estar aquí hoy en la conferencia de Node.

Y hoy voy a hablar sobre desmitificar las fugas de memoria. Así que las fugas de memoria a menudo se consideran algo difícil y complicado de resolver. Pero, ¿es realmente así? ¿Y cómo podemos facilitar el proceso?

Para llegar a eso, primero me gustaría responder a la pregunta de qué es realmente una fuga de memoria. Y estoy consultando Wikipedia para responder a esa pregunta. Una fuga de memoria es cuando un programa de computadora gestiona incorrectamente la memoria de acceso aleatorio. De una manera que la memoria, que ya no se necesita, no se libera. Como tal, vamos a acumular más y más memoria con el tiempo. Y el programa, en el peor de los casos, podría simplemente colapsar porque no hay más memoria para asignar. Y ese es realmente el peor de los casos. O tal vez estás en un entorno de nube y vas a tener que pagar mucho más dinero porque tienes un autoescalado activo y se asigna más y más memoria allí.

Así que aquí tenemos un gráfico que claramente te muestra cómo se vería una fuga de memoria en comparación con el uso de memoria y el tiempo que el programa se ejecuta. Y la línea amarilla es un programa perfecto prácticamente. Se inicia y asignas algo de memoria y luego hay algunos altibajos y esto es perfecto para cada programa prácticamente. A veces los picos pueden ser más altos o bajar un poco de nuevo, pero en promedio es la línea, la línea plana. Y la línea azul es claramente una fuga de memoria porque con el tiempo solo asignas más y más memoria sin liberarla nuevamente. Y esto es malo.

Entonces, ¿cómo manejamos la memoria en JavaScript en particular? Porque no tenemos que preocuparnos por ello, ¿verdad? Todo esto se hace de manera transparente y esto es perfecto. Y la memoria simplemente se libera. ¿Por qué debería haber una fuga de memoria en primer lugar? Así que la memoria se divide en una memoria de pila y una memoria de montón. La memoria de montón es una memoria asignada dinámicamente y la pila es hecha por el sistema operativo en un caso típico. Cada hilo tiene algo de memoria de pila. Es el algoritmo de último en entrar, primero en salir, también llamado lethal. Es muy simple, es súper rápido y la memoria que se asigna en la pila se recupera automáticamente tan pronto como la función sale. Cuando comparamos eso con la memoria de montón, hay muchas cosas sucediendo porque la memoria de pila normalmente solo contiene punteros a la función que se está ejecutando actualmente. Y si empujas en la pila, el puntero que se está ejecutando actualmente, entonces llegamos al montón, que es la memoria asignada dinámicamente. Y aquí tenemos una buena visión general de V8 que se hizo para el Times of India.

2. Memory Allocation and Garbage Collection

Short description:

Hay muchas cosas sucediendo. JSObjects son asignados, tenemos código fuente de JavaScript, código optimizado, tenemos código de expresión regular, cadenas, y mucho, mucho más. La memoria del montón, en V8 en particular, se divide en tres áreas. Tenemos la generación joven, generación intermedia, y generación vieja. El recolector de basura es responsable de liberar automáticamente la memoria que asignamos, pero a veces puede volverse loco.

Hay muchas cosas sucediendo. JSObjects son asignados, tenemos código fuente de JavaScript, código optimizado, tenemos código de expresión regular, cadenas, y mucho, mucho más. Así que, esta es la memoria principal para nuestro programa en este caso.

Y la memoria del montón, en V8 en particular, se divide en tres áreas. Nuevamente, tenemos la generación joven. Así que, tan pronto como asignamos una nueva variable, digamos que decimos let the pool is the string test, entonces vas a asignar la memoria test y se va a poner en la generación joven. Esta memoria es relativamente pequeña. Principalmente JavaScript tendrá variables intermedias que usas para calcular el siguiente valor inmediatamente. Y no necesitas la variable tan pronto como calculas tu siguiente valor. Todo esto se hace de manera sincrónica. Así que, queremos desechar toda esa memoria que no necesitamos tan pronto como sea posible. Así que, esta generación joven solo sobrevivirá a una llamada carrera de recolección. Esta es la primera carrera donde nuestro programa para crear una memoria va a intentar deshacerse de esas variables que ya no se usan. Y si alguna variable sobrevive a esa carrera, entonces se empuja a la generación intermedia. Y si sobrevive a la segunda carrera, entonces se empuja a la generación vieja. Esta es la parte más grande de la aplicación. Normalmente se usa para variables largas y usadas. Así que, cosas que reutilizas en cada aplicación que podrían contener punteros a muchas cosas. Y usamos un algoritmo diferente para liberar la memoria en este caso. Y el algoritmo usado allí se llama MarkSweep. Comenzamos desde nuestro objeto raíz. El objeto raíz en un navegador sería el objeto window, y en Node.js, es global. Mientras que en JavaScript moderno, estaría en ambos, solo global disk. Y usamos algo así como, similar a un algoritmo recursivo donde comenzamos con el objeto raíz y simplemente conectamos cada punto. Intentamos conectar cada nodo que está algo conectado a su objeto raíz. Todos los demás nodos, todas las demás variables o asignaciones van a ser liberadas. Y esto debería ser mayormente ideal para liberar toda la memoria que no se usa.

Así que, ya hablé de que nosotros como desarrolladores no tenemos que preocuparnos por la memoria que asignamos porque va a ser liberada automáticamente. Lo que se hace en el fondo es que se ejecuta un llamado recolector de basura y ese recolector de basura tiene mucho que hacer y en algún momento podría incluso volverse loco y no, no funciona como anticipamos que lo haría. Así que tenemos que mirar eso un poco más de cerca.

3. Typical Memory Leaks and Issues

Short description:

Un tipo de dato incorrecto y ejecutar demasiadas cosas en paralelo pueden causar problemas de memoria. Los event listeners y closures también pueden contribuir a las fugas de memoria. Los file descriptors, cuando no se cierran correctamente, también pueden causar problemas. Comprender los detalles de implementación de JavaScript es crucial.

¿Cuáles son las fugas de memoria o problemas típicos? Esto no está en un orden específico y no todos son fugas de memoria reales, por ejemplo, los dos primeros. Entonces, un tipo de dato incorrecto es algo que todavía tenemos que investigar porque esto es una cosa muy típica que encontré frecuentemente. A menudo los programas usan tipos de memoria que no son eficientes para la tarea que quieres resolver. Y luego, cuando manejas datos grandes, vas a asignar una gran cantidad de memoria, aunque no necesitarías eso, simplemente usando un tipo de dato diferente.

Así que usar el tipo de dato correcto también puede ayudarte a prevenir que tu programa se bloquee en caso de que alguna vez encuentres datos más grandes. Y el segundo es que también intentamos ejecutar muchas cosas en paralelo. Probablemente a todos nos encantan las promises y async await, y usamos promise all para mejorar el rendimiento de la aplicación, porque normalmente, como con Node, las cosas se ejecutan en un solo hilo y todavía queremos hacer múltiples cosas a la vez, básicamente, para tener múltiples llamadas de procedimiento remoto. Pero cuando usas demasiados de esos al mismo tiempo, también tenemos que asignar memoria para todas estas etapas. Y cuando aún no han terminado, también podrían causar una excepción en tu programa porque no queda más memoria. Así que esto también es importante de investigar.

Ahora vamos al primer bucle de memoria real, los event listeners. Así que algo que mucha gente sabe es que en los navegadores, como hace un tiempo, era típico simplemente adjuntar event listeners inmediatamente a un elemento DOM específico en una lista de la que te importaría que un evento se disparara. Y luego a veces tenemos que simplemente agregar muchos y muchos event listeners a todos estos elementos. En su lugar, quieres tener un solo event listener en un nodo superior, que luego escucharía todos los eventos provenientes de todos estos nodos debajo. Y luego no tienes que adjuntar tantos listeners porque los event listeners también se suman en memoria. Y a veces simplemente agregamos un nuevo event listener para cada evento entrante. Esto sería un error de programación, pero ocurre frecuentemente.

Y más difícil aún son los closures. Porque a veces los closures impiden que el recolector de basura sepa cuándo una variable ya no se usa. Y cuándo podemos disponer de esa memoria. Así que este es complicado. Luego los file descriptors también pueden causar problemas. Porque cuando abres un archivo, hay una cantidad limitada de archivos que puedes abrir al mismo tiempo. Y cuando simplemente ejecutamos nuestro programa, normalmente funciona, aunque no cerremos el archivo después de abrirlo, eso también puede causar problemas. Así que siempre tenemos que asegurarnos de cerrarlo tanto en caso de éxito como de no éxito. Así que siempre deberías tener como un enlace de archivo que no importa si estás abriendo exitosamente ese archivo o no. Porque a veces puede haber algo en el medio y aún lo abres. Pero hubo un error en otro lugar. Y aún tienes que cerrar ese. La parte más complicada es que en JavaScript, y cuando miramos en Chrome o cualquier navegador Chromium y Node.js también se ejecuta con V8, entonces tenemos que conocer algunos detalles de implementación.

4. Reading Data in Chunks

Short description:

Leer demasiados datos en un solo fragmento puede ser ineficiente y provocar problemas de asignación de memoria. En su lugar, transmitir datos en pequeños fragmentos es más rápido y elimina la necesidad de una asignación excesiva de memoria.

Voy a entrar en algunos de esos en un momento. Aquí hay un ejemplo de lo malo que puede ser si leemos demasiados datos en un solo fragmento también. Así que tenemos un servidor HTTP y leemos un archivo grande, el usuario solicita un archivo. Esto va a tomar un tiempo y no va a ser eficiente y va a asignar mucha memoria porque primero tenemos que leer toda esa memoria en la aplicación y tan pronto como esté completamente cargada, vamos a comenzar a enviar esos datos al usuario, no antes. Y cuando no hay un solo usuario sino muchos usuarios solicitando la misma ruta al mismo tiempo, también podríamos tener un problema de memoria porque entonces la memoria total disponible ya no va a ser suficiente y la aplicación va a fallar. En su lugar, deberíamos preocuparnos por transmitir los datos en pequeños fragmentos. Va a ser mucho más rápido y no tenemos que preocuparnos por la asignación de memoria más. Simplemente obtenemos la primera parte del archivo que queremos leer y no importa si es como múltiples gigabytes de tamaño, aún podemos enviarlo inmediatamente en digamos unos pocos kilobytes. Y tan pronto como esté hecho, estará hecho. La memoria en la línea va a ser muy plana. No tenemos que asignar más que los pequeños fragmentos que queremos leer.

5. Handling File Descriptors and Event Listeners

Short description:

Y con los descriptores de archivo, también nos preocupamos por manejar el error. Abrimos el archivo, queremos escribir algo en él, pero nunca cerramos ese archivo de nuevo. Los event listeners podrían verse algo así. Imaginemos que tienes una base de datos que está basada en eventos y quieres escribir algo en ella. Las cadenas son, como mencioné, tenemos esta cadena muy larga, de un millón de caracteres, y solo queremos preocuparnos por los primeros 20 caracteres. Sigue siendo difícil de prevenir, pero deberíamos preocuparnos por ello. De lo contrario, la aplicación podría simplemente fallar y esta es la peor situación. Y si sucede, bueno, tenemos que lidiar con esa situación y lidiar con esas fugas de memoria puede ser muy problemático. Tenemos que saber cómo identificar los puntos que causan esa fuga de memoria. Y esta es la parte más importante para mí. Así que aquí es donde nos vamos a centrar ahora, cómo detectar y solucionar esas fugas de memoria.

Y con los file descriptors, también nos preocupamos por manejar el error. Abrimos el archivo, queremos escribir algo en él, pero nunca cerramos ese archivo de nuevo. Y si hacemos eso demasiadas veces, una aplicación también tendría un problema. Así que siempre debemos asegurarnos de cerrar ese file descriptor. Y eso se hace en el blog de la última semana, como mencioné antes.

Los event listeners podrían verse algo así. Imaginemos que tienes una base de datos que está basada en eventos y quieres escribir algo en ella. Y tenemos un event listener en data. Así que hay un servidor HTTP, y quiere conectarse a una base de datos y quiere escribir algo en ella. Así que escribimos en ella y luego va a haber una respuesta en el evento de data. Pero en este caso, cometimos un error porque en cada solicitud de usuario, añadimos un nuevo event listener a esa base de datos en lugar de solo uno único al principio. Y luego tenemos muchos event listeners al final que son todos muy pequeños, pero va a terminar como una línea azul que viste antes. Y este es el peor, prácticamente. Es algo que se ve con mucha frecuencia y que se reporta, tanto en el Node.js issue reporting como en el de V8 porque esta es una parte específica de V8 que simplemente tienes que conocer.

Las cadenas son, como mencioné, tenemos esta cadena muy larga, de un millón de caracteres, y solo queremos preocuparnos por los primeros 20 caracteres. Así que cortamos los 20 y normalmente imaginarías que el resto simplemente se lee porque no lo usamos más. En su lugar, solo tenemos referencia porque internamente en V8 hay mucha optimización en marcha y trata de ser muy rápido y eficiente en memoria al mismo tiempo. Es una heurística que se usa que podría no siempre funcionar como se anticipa. Imaginemos que tenemos la cadena test y la cadena ABC y quieres comparar esas. En lugar de asignar un nuevo fragmento de memoria que consistiría en test A, B, C, simplemente asignaría una nueva cosa muy pequeña que apunta a la cadena test y a la cadena ABC y diría, soy la combinación de ambas. Es como una estructura de árbol que podrías imaginar. Cuando queremos cortar algo de nuevo, también solo va a apuntar a la cadena original y dice, hey, tengo este punto de inicio y este punto final de esa cadena, pero no va a liberar el resto de la cadena incluso si ya no se usa. Y eso podría terminar en una mala situación donde ensuciamos nuestro programa una y otra vez y como todos sabemos, no deberíamos ensuciar nuestro entorno. Sigue siendo difícil de prevenir, pero deberíamos preocuparnos por ello. De lo contrario, la aplicación podría simplemente fallar y esta es la peor situación. Y si sucede, bueno, tenemos que lidiar con esa situación y lidiar con esas fugas de memoria puede ser muy problemático. Incluso podríamos tener algunos problemas de ira y pasar mucho tiempo mirando algo sin realmente saber qué buscar. Así que tenemos que saber cómo identificar los puntos que causan esa fuga de memoria. Y esta es la parte más importante para mí. Así que aquí es donde nos vamos a centrar ahora, cómo detectar y solucionar esas fugas de memoria.

6. Tools and Techniques for Identifying Memory Leaks

Short description:

Hay herramientas y flags para identificar fugas de memoria en Node.js, como 'inspect' y 'trace GC'. El flag 'inspect' te permite conectarte al inspector de Chrome u otras herramientas. El comando 'trace GC' muestra lo que hace el recolector de basura en diferentes momentos. El flag 'abort on uncaught exception' provoca un volcado de heap cuando la aplicación falla. También se pueden usar herramientas como LM node. Para saber más, visita nodes.js.org guides debugging getting started. Ahora te mostraré algunos ejemplos de código, incluyendo un programa que confunde al recolector de basura. Podemos usar el flag 'inspect' para ver el objetivo remoto y explorar instantáneas de heap.

Hay muchas herramientas y también flags para identificar fugas de memoria en Node.js. La primera es un dash dash inspect que puedes pasar al runtime de Node.js. Y luego puedes conectarte, por ejemplo, al inspector de Chrome, pero también a otras herramientas. Y también tenemos un flag que se llama trace GC. Con el comando trace GC, es posible ver lo que hace el recolector de basura en diferentes momentos. También es interesante saberlo.

A veces es muy difícil identificar realmente el error. Y entonces podrías querer usar el dash dash abort on uncaught exception, porque esto va a causar automáticamente un llamado volcado de heap. Y el volcado de heap es el estado de la memoria en ese momento actual. Así que cuando la aplicación falla, debido a esa excepción, podemos simplemente mirar lo que era la aplicación en términos de memoria en ese estado. Y hay más herramientas como LM node para examinar eso. Si te interesan más herramientas, solo revisa este sitio web, nodes.js.org guides debugging getting started, y encontrarás mucha información para hacerlo.

Y quiero mostrarte algo de codificación en realidad. Por ejemplo, para el de la cadena. Así que en este caso, tengo el pequeño programa y estoy usando el módulo V8 de Node.js y tenemos una variable que es count. Solo la tenemos establecida en cero y tenemos una variable pool. Tenemos la función run, y esto va a hacer algunas cosas que vamos a ver en un segundo. Tenemos este intervalo. Se ejecuta cada milisegundo. La función run se activa cada milisegundo y luego creamos instantáneas cada dos segundos. Sabemos cuál es el estado de la aplicación en ese momento. Y aquí tenemos esta función interna y va a referenciar la original, mientras que la original va a referenciar nuevamente a pool y pool se actualiza en cada ejecución. Así que aquí simplemente confundimos al recolector de basura debido a la forma en que estas variables están todas conectadas entre sí. Y veamos qué pasaría en este caso. Este sería este. Así que quiero revisar ese programa. Así que ahora solo abro drone inspect y debido al flag dash dash inspect, ahora puedo ver el objetivo remoto. Así que voy a inspeccionar esto. Y aquí ves este resumen, selecciona profiling pipe, heap snapshot, allocation sampling, etc. Y quiero examinar algunas de estas instantáneas de heap.

7. Analyzing Memory Allocation

Short description:

Entonces voy a cargar uno. El programa crea nuevos con el tiempo. Podemos comparar uno de estos heaps y ver dónde se fue toda tu memoria. Por ejemplo, hay una gran diferencia en el delta de tamaño de 2.4 megabytes. Vemos que hay muchas strings. Ahora sabemos que tiene algo que ver con funk. Definitivamente sabemos que asignamos demasiadas de estas strings porque puedes verlas todas. Son muy grandes y no son libres. Tienes que investigar eso. Esto también es posible usarlo en un navegador. Puedes iniciarlo.

Entonces voy a cargar uno. Y como puedes ver, el programa crea nuevos con el tiempo. Así que vamos a abrir el primero. Y vamos a abrir el último. Y también voy a detener el programa. Ahora tenemos estos dos, porque aquí puedes investigarlo y hay como muchos datos sucediendo. Y no está realmente claro qué buscar. Pero podemos compararlo simplemente haciendo clic en comparación. Y ahora podemos comparar uno de estos heaps, no solo instantáneas con el otro. Y entonces es mucho más fácil ver dónde se fue toda tu memoria. Por ejemplo, aquí podemos ver que hay una gran diferencia en el delta de tamaño de 2.4 megabytes. Así que este es claramente un punto que quieres investigar. Y cuando lo investigamos, vemos que hay muchas strings. Estas strings, nuevamente, cuando las miramos, están primero en esta variable, en esta string. Y la string está en un objeto específico en ese punto de memoria. Y esto está en el contexto original y del sistema. Bien, el contexto está en funk. Ah, esto es algo que conocemos en nuestro programa. Así que sabemos que funk estaba aquí. Este es nuestro funk. Y luego puedes identificar la causa real. Ahora sabemos que tiene algo que ver con funk. Aunque no lo veas inmediatamente, definitivamente sabemos que asignamos demasiadas de estas strings porque puedes verlas todas aquí. Y son muy grandes. Y no son libres. Así que sabes que tienes que investigar eso.

Mi tiempo se está acabando, así que tengo que apresurarme un poco. Pero quiero decir que esto también es posible usarlo en un navegador. Porque esta herramienta también está disponible allí. Y por ejemplo, puedes iniciarlo.

8. Fixing Memory Leaks and Tools

Short description:

Haz clic en Inspeccionar, ve a memoria y visualiza la vista general. Otro programa, StringCrash, ejemplifica el problema. Pasos para solucionar la fuga de memoria: monitorear la memoria, perfilar con herramientas como Inspeccionar y tomar instantáneas. Ten cuidado ya que las instantáneas son costosas. Compara las instantáneas para identificar la fuga y solucionarla. Hay numerosas herramientas disponibles para ayudar, pero recuerda que la memoria es costosa y puede ralentizar tu sistema.

Haz clic en él. Y al hacer clic en Inspeccionar, y luego ir a memoria. Y aquí está la vista general de eso también. Quiero mostrarte un poco más de otro programa rápidamente. Por ejemplo, este es StringCrash. Así que aquí, tengo ese problema del que había hablado con el de V8. Podemos mirar el código. Esto está haciendo exactamente lo que he mencionado antes. Y el programa se bloquea muy rápido porque no puede asignar más memoria.

Muy bien. Así que pasos para solucionar la fuga de memoria. En primer lugar, por favor monitorea tu memoria. Usa, por ejemplo, un APM o algo así. Y luego sabes cómo se ve el perfil de tu memoria. Perfílalo con herramientas como la de Inspeccionar. Y toma montones de instantáneas. Pero ten en cuenta que son muy costosas. No querrás hacer eso en producción en la mayoría de los casos. Siempre intenta hacerlo en un entorno controlado que es el testing de aeropuerto. Si tienes que hacerlo en un entorno de producción, entonces podrías hacerlo con una configuración muy estricta en un tiempo de espera, solo un contenedor específico o algo así, para hacerlo solo de manera muy infrecuente. Y luego puedes comparar tales montones de instantáneas. Esa es una de las formas más eficientes de identificar la fuga desde mi perspectiva. Y luego puedes simplemente identificarlo y solucionar el problema tan pronto como sepas de qué se trata.

Hay muchas herramientas que pueden ayudarte. Puedes revisarlo en línea en el sitio web del que he hablado. La memoria es costosa, así que no solo en términos de costo cuando tienes que pagar dólares o cualquier otra moneda por ella, sino también en el aspecto del rendimiento, porque cuando asignas más y más memoria tu sistema va a ralentizarse. Así que realmente quieres prevenir eso. Las instantáneas son costosas por una razón similar. Va a ser como una aplicación congelada en ese momento. No puede hacer nada más mientras reúne toda la memoria de la aplicación.

9. Fixing Memory Leaks and Restarting Applications

Short description:

Elige cuidadosamente tu tipo de datos y tu estructura de datos. Intenta solucionar el problema real en su lugar. Uno de mis días más productivos fue deshacerme de 1,000 líneas de código. 71% es un problema común que la gente encuentra. Reiniciar la aplicación no es una solución duradera.

Elige cuidadosamente tu tipo de datos y tu estructura de datos, y solo reinicia tu aplicación como último recurso. Intenta solucionar el problema real en su lugar.

Así que muchas gracias por estar aquí. Quiero terminar con una de mis citas favoritas de Ken Thompson. Uno de mis días más productivos fue deshacerme de 1,000 líneas de código, y puedo relacionarme muy bien con eso. Que tengas un gran día.

Hola. Hola, Ruben. Es bueno verte aquí en el escenario conmigo. Un honor tenerte, por supuesto. ¿Qué piensas? 71%, ¿es este el porcentaje que esperabas? Bastante. Es realmente algo común que la gente encuentra. Y es algo que a menudo la gente solo intenta evitar en lugar de realmente profundizar en el problema y solucionarlo. Como, he visto aplicaciones que se reinician una vez al día, al menos, porque tenían una fuga de memoria que no pudieron encontrar, o que intentaron simplemente reducir el uso de memoria en general o aumentar la memoria que podían usar, y cosas así. Y antes de que tuvieran que reiniciar la aplicación, eso es algo, obviamente, que no es agradable. Tienes que pagar mucho dinero por ello. Así que solucionarlos es realmente importante. Sí, realmente lo es. Y sí, bueno, reiniciar no es realmente una solución duradera, por supuesto.

10. Handling String Slice Example

Short description:

Para evitar mantener la cadena original en memoria al usar el ejemplo de string slice, necesitas entender el funcionamiento interno de V8. Ciertas operaciones, como aplanar cadenas, pueden asignar un nuevo fragmento de memoria y liberar la memoria original. La biblioteca 'flat string' en NPM puede ayudar con esto al crear internamente una nueva cadena como un tipo de dato diferente. Es importante ser cauteloso al asignar cadenas para prevenir problemas de memoria.

Quiero ir a la primera pregunta de uno de los miembros de nuestra audiencia. Es una pregunta de I Am. La pregunta es, ¿cómo manejarías mejor el ejemplo de string slice para evitar que la cadena original se mantenga en memoria? Entonces, en este caso, tienes que conocer sobre el funcionamiento interno de V8 bastante bien, y entender cómo funcionan estas cosas. Y hay algunas operaciones que aplanarían las cadenas. Así que, de hecho, asignarían un nuevo fragmento de memoria completo para el camino que se requiere para tu caso de uso. Y luego ya no habría una referencia fuerte a la memoria original que asignaste, y luego sería liberada. Hay una biblioteca por ahí que realmente hace eso como una operación muy simple. Originalmente, solo convertía la cadena a un número en el medio. Luego sería internamente convertida bastante. Y trata de crear una nueva cadena internamente en V8. Solo está usando un truco para hacer que esa cadena internamente sea un tipo de dato diferente. Y se llama flat string, escrito como F-L-A-T-S-T-R. Y puedes echarle un vistazo en NPM. Sí, exactamente. Puedes echarle un vistazo allí, y solo revisar algunos benchmarks. Pero principalmente, deberías tener cuidado sobre cómo asignas cadenas para prevenirlo en primer lugar. Intenta evitarlo, por supuesto. Pero en lugar de parchearlo más tarde.

QnA

Identifying Memory Leaks and Tools

Short description:

Existen herramientas específicas para identificar fugas de memoria, que se pueden encontrar en el sitio web de Node.js. Al identificar una fuga de memoria, es importante monitorear tus recursos y usar herramientas como un APM para detectar fugas. Para inspeccionar e identificar fugas de memoria en funciones de AWS Lambda o Google Firebase, necesitas ejecutar el código en un entorno donde tengas control total y puedas crear volcados de memoria. Se recomienda hacer esto en un entorno de staging. Las pruebas automatizadas para fugas de memoria no son comunes, pero el monitoreo puede ayudar a identificar cuándo el uso de memoria excede los límites esperados. Git bisect se puede usar para rastrear cambios que pueden haber causado fugas de memoria.

La siguiente pregunta es de CreoZot. ¿Hay alguna herramienta específica para identificar fugas de memoria que puedas recomendar? Entonces, señalé la página web que podrías visitar. Y hay muchas herramientas diferentes que puedes usar. Está en el sitio web de Node.js. Y puedo recomendar encarecidamente que le eches un vistazo.

Muy bien. La siguiente pregunta es de Alexey. ¿Cómo inspeccionar e identificar fugas de memoria en AWS, Lambda, o funciones de Google Firebase? Debería ser similar, de todos modos. Siempre y cuando tengas acceso a, sí, debería ser. Bueno, primero tienes que identificar la fuga, que tienes una fuga. Eso es normalmente lo que hace el monitoreo, también. Normalmente monitoreas tus recursos. Esa es la primera parte. Usas, por ejemplo, un APM para eso. Y tan pronto como identifiques que hay de hecho una fuga, querrás ejecutar el código en cualquier entorno sobre el que tengas control total y que puedas inspeccionar. Y puedes, por ejemplo, siempre crear volcados de memoria en cualquier entorno. Así que esa sería una forma de hacerlo. Esa sería una de las formas que podrías usar. Personalmente prefiero los volcados de memoria, y obviamente deberías tratar de no hacerlo en producción. Siempre trata de hacerlo en un entorno de staging, si es posible.

OK. La siguiente pregunta es de André Calazans. ¿Has visto o hecho pruebas automatizadas para fugas de memoria? ¿Y sabes si hay alguna manera de diferenciar fugas en vivo de fugas de memoria reales? Así que no he visto pruebas reales para fugas de memoria, pero si lo monitoreas, entonces normalmente deberías tener una notificación tan pronto como en cualquier parte de tu aplicación la memoria se salga de control, porque normalmente establecerías un límite para la memoria que esperas usar. Y luego, tan pronto como llegue a ese punto, deberías echar un vistazo más de cerca. Y luego tal vez volver a tu historial de Git y ver qué ha cambiado allí. Es un proceso manual a partir de ahí, pero al menos tienes una marca de tiempo. Algo salió mal después de ese despliegue. Así que en este caso, podrías usar fácilmente git bisect. Y git bisect es una característica muy poderosa.

Identifying and Fixing Memory Leaks

Short description:

Escribe una prueba para activar la fuga de memoria e identificar el código que la causa. Usa el método bisect para encontrar el commit que introdujo la fuga.

Entonces escribe una prueba que activaría la fuga de memoria. Así sabes al menos que algo en algún lugar la causa, incluso si aún no la has identificado. Y luego quieres identificar el código. Así sabes, OK, cuando ejecuto este código, y luego en algún momento, por ejemplo, la aplicación va a fallar después de un par de segundos o así. Y entonces sabes que la fuga está ahí. Luego lo bisectas, y eso es una pequeña cosa rítmica donde simplemente avanzas desde ambos lados. Y si no falla, entonces sabrías, OK, este código no es una fuga. Y así puedes bisectarlo hasta que encuentres el commit exacto que introdujo la fuga. Inteligente.

Large JSON Objects and Memory Limits

Short description:

¿Pueden los objetos JSON grandes mantenidos en memoria causar fugas de memoria? Hay un límite estricto para cada tipo de dato. Para las cadenas, es aproximadamente 2 elevado a la potencia de 28 caracteres. Superar este límite resultará en un error. Sin embargo, no estoy al tanto de ningún límite para los objetos JSON. Afortunadamente, normalmente no alcanzo esos límites.

La siguiente pregunta es de nuevo de Alexei. ¿Pueden los objetos JSON grandes mantenerse en memoria? Lo siento. ¿Pueden los objetos JSON grandes mantenidos en memoria causar fugas de memoria? La estructura JSON no causa particularmente más fugas de memoria que cualquier otra cosa como estructura de datos. Así que sí. Pero creo que Alexei quiere decir si es un problema si un objeto JSON se vuelve demasiado grande. En general, hay un límite estricto en los tipos de datos, para cada tipo de dato. Muy cierto. Por ejemplo, para las cadenas creo, si recuerdo correctamente, es aproximadamente 2 elevado a la potencia de 28 caracteres que una cadena podría tener de tamaño. Y tan pronto como superes ese límite, habría un error. Y probablemente tendríamos ese caso si tienes el JSON como una cadena. Y si lo tienes como un objeto. No conozco ningún límite en este caso. Podría haber uno. Y definitivamente hay uno para algunos tipos de datos. Pero afortunadamente, normalmente no alcanzo esos límites.

Ruben's Experience with Memory Leaks

Short description:

Ruben comparte su experiencia con fugas de memoria, recordando una vez cuando tuvo que reiniciar una aplicación una vez al día debido a una fuga de memoria. Menciona que no pudo depurar la aplicación en ese momento. Ruben también menciona que ha tenido la suerte de no encontrar fugas de memoria personales en los últimos años.

Afortunado tú. Última pregunta para la que tenemos tiempo. Y es una pregunta de George Turley. Ya que estamos hablando de fugas de memoria, ¿cuál fue la peor fuga de memoria que encontraste? Y si pudiste encontrarla, ¿cómo la solucionaste si pudiste? Así que la peor que encontré personalmente... ya hace un tiempo. Probablemente sea la que mencioné antes de reiniciar la aplicación una vez al día. Estaba usando la aplicación, la estaba desarrollando, y no tenía las posibilidades de depurarla. Pero definitivamente fue la que más me molestó. Yo... Ya no estoy seguro sobre la mía personal que solucioné. Tuve suerte en los últimos años recientes y no encontré personalmente ninguna de esas. Mantengámoslo así, entonces, Ruben.

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

Es una jungla ahí fuera: ¿Qué está pasando realmente dentro de tu carpeta Node_Modules?
Node Congress 2022Node Congress 2022
26 min
Es una jungla ahí fuera: ¿Qué está pasando realmente dentro de tu carpeta Node_Modules?
Top Content
The talk discusses the importance of supply chain security in the open source ecosystem, highlighting the risks of relying on open source code without proper code review. It explores the trend of supply chain attacks and the need for a new approach to detect and block malicious dependencies. The talk also introduces Socket, a tool that assesses the security of packages and provides automation and analysis to protect against malware and supply chain attacks. It emphasizes the need to prioritize security in software development and offers insights into potential solutions such as realms and Deno's command line flags.
Cargadores ESM: Mejorando la carga de módulos en Node.js
JSNation 2023JSNation 2023
22 min
Cargadores ESM: Mejorando la carga de módulos en Node.js
Top Content
ESM Loaders enhance module loading in Node.js by resolving URLs and reading files from the disk. Module loaders can override modules and change how they are found. Enhancing the loading phase involves loading directly from HTTP and loading TypeScript code without building it. The loader in the module URL handles URL resolution and uses fetch to fetch the source code. Loaders can be chained together to load from different sources, transform source code, and resolve URLs differently. The future of module loading enhancements is promising and simple to use.
Hacia una Biblioteca Estándar para Runtimes de JavaScript
Node Congress 2022Node Congress 2022
34 min
Hacia una Biblioteca Estándar para Runtimes de JavaScript
Top Content
There is a need for a standard library of APIs for JavaScript runtimes, as there are currently multiple ways to perform fundamental tasks like base64 encoding. JavaScript runtimes have historically lacked a standard library, causing friction and difficulty for developers. The idea of a small core has both benefits and drawbacks, with some runtimes abusing it to limit innovation. There is a misalignment between Node and web browsers in terms of functionality and API standards. The proposal is to involve browser developers in conversations about API standardization and to create a common standard library for JavaScript runtimes.
Diagnostics de Node.js listos para usar
Node Congress 2022Node Congress 2022
34 min
Diagnostics de Node.js listos para usar
This talk covers various techniques for getting diagnostics information out of Node.js, including debugging with environment variables, handling warnings and deprecations, tracing uncaught exceptions and process exit, using the v8 inspector and dev tools, and generating diagnostic reports. The speaker also mentions areas for improvement in Node.js diagnostics and provides resources for learning and contributing. Additionally, the responsibilities of the Technical Steering Committee in the TS community are discussed.
El Estado de Node.js 2025
JSNation 2025JSNation 2025
30 min
El Estado de Node.js 2025
The speaker covers a wide range of topics related to Node.js, including its resilience, popularity, and significance in the tech ecosystem. They discuss Node.js version support, organization activity, development updates, enhancements, and security updates. Node.js relies heavily on volunteers for governance and contribution. The speaker introduces an application server for Node.js enabling PHP integration. Insights are shared on Node.js downloads, infrastructure challenges, software maintenance, and the importance of update schedules for security.
Compatibilidad con Node.js en Deno
Node Congress 2022Node Congress 2022
34 min
Compatibilidad con Node.js en Deno
Deno aims to provide Node.js compatibility to make migration smoother and easier. While Deno can run apps and libraries offered for Node.js, not all are supported yet. There are trade-offs to consider, such as incompatible APIs and a less ideal developer experience. Deno is working on improving compatibility and the transition process. Efforts include porting Node.js modules, exploring a superset approach, and transparent package installation from npm.

Workshops on related topic

Masterclass de Node.js
Node Congress 2023Node Congress 2023
109 min
Masterclass de Node.js
Top Content
Workshop
Matteo Collina
Matteo Collina
¿Alguna vez has tenido dificultades para diseñar y estructurar tus aplicaciones Node.js? Construir aplicaciones que estén bien organizadas, sean probables y extensibles no siempre es fácil. A menudo puede resultar ser mucho más complicado de lo que esperas. En este evento en vivo, Matteo te mostrará cómo construye aplicaciones Node.js desde cero. Aprenderás cómo aborda el diseño de aplicaciones y las filosofías que aplica para crear aplicaciones modulares, mantenibles y efectivas.

Nivel: intermedio
Construir y Desplegar un Backend Con Fastify & Platformatic
JSNation 2023JSNation 2023
104 min
Construir y Desplegar un Backend Con Fastify & Platformatic
Top Content
WorkshopFree
Matteo Collina
Matteo Collina
Platformatic te permite desarrollar rápidamente GraphQL y REST APIs con un esfuerzo mínimo. La mejor parte es que también te permite desatar todo el potencial de Node.js y Fastify siempre que lo necesites. Puedes personalizar completamente una aplicación de Platformatic escribiendo tus propias características y plugins adicionales. En la masterclass, cubriremos tanto nuestros módulos de Open Source como nuestra oferta en la Nube:- Platformatic OSS (open-source software) — Herramientas y bibliotecas para construir rápidamente aplicaciones robustas con Node.js (https://oss.platformatic.dev/).- Platformatic Cloud (actualmente en beta) — Nuestra plataforma de alojamiento que incluye características como aplicaciones de vista previa, métricas integradas e integración con tu flujo de Git (https://platformatic.dev/). 
En esta masterclass aprenderás cómo desarrollar APIs con Fastify y desplegarlas en la Platformatic Cloud.
Construyendo un Servidor Web Hiper Rápido con Deno
JSNation Live 2021JSNation Live 2021
156 min
Construyendo un Servidor Web Hiper Rápido con Deno
Workshop
Matt Landers
Will Johnston
2 authors
Deno 1.9 introdujo una nueva API de servidor web que aprovecha Hyper, una implementación rápida y correcta de HTTP para Rust. El uso de esta API en lugar de la implementación std/http aumenta el rendimiento y proporciona soporte para HTTP2. En este masterclass, aprende cómo crear un servidor web utilizando Hyper en el fondo y mejorar el rendimiento de tus aplicaciones web.
0 a Auth en una Hora Usando NodeJS SDK
Node Congress 2023Node Congress 2023
63 min
0 a Auth en una Hora Usando NodeJS SDK
WorkshopFree
Asaf Shen
Asaf Shen
La autenticación sin contraseña puede parecer compleja, pero es fácil de agregar a cualquier aplicación utilizando la herramienta adecuada.
Mejoraremos una aplicación JS de pila completa (backend de Node.JS + frontend de React) para autenticar usuarios con OAuth (inicio de sesión social) y contraseñas de un solo uso (correo electrónico), incluyendo:- Autenticación de usuario - Administrar interacciones de usuario, devolver JWT de sesión / actualización- Gestión y validación de sesiones - Almacenar la sesión para solicitudes de cliente posteriores, validar / actualizar sesiones
Al final del masterclass, también tocaremos otro enfoque para la autenticación de código utilizando Flujos Descope en el frontend (flujos de arrastrar y soltar), manteniendo solo la validación de sesión en el backend. Con esto, también mostraremos lo fácil que es habilitar la biometría y otros métodos de autenticación sin contraseña.
Tabla de contenidos- Una breve introducción a los conceptos básicos de autenticación- Codificación- Por qué importa la autenticación sin contraseña
Requisitos previos- IDE de tu elección- Node 18 o superior
GraphQL: De Cero a Héroe en 3 horas
React Summit 2022React Summit 2022
164 min
GraphQL: De Cero a Héroe en 3 horas
Workshop
Pawel Sawicki
Pawel Sawicki
Cómo construir una aplicación GraphQL fullstack (Postgres + NestJs + React) en el menor tiempo posible.
Todos los comienzos son difíciles. Incluso más difícil que elegir la tecnología es desarrollar una arquitectura adecuada. Especialmente cuando se trata de GraphQL.
En este masterclass, obtendrás una variedad de mejores prácticas que normalmente tendrías que trabajar en varios proyectos, todo en solo tres horas.
Siempre has querido participar en un hackathon para poner algo en funcionamiento en el menor tiempo posible, entonces participa activamente en este masterclass y únete a los procesos de pensamiento del instructor.
Dominando Node.js Test Runner
TestJS Summit 2023TestJS Summit 2023
78 min
Dominando Node.js Test Runner
Workshop
Marco Ippolito
Marco Ippolito
Node.js test runner es moderno, rápido y no requiere bibliotecas adicionales, pero entenderlo y usarlo bien puede ser complicado. Aprenderás a utilizar Node.js test runner a su máximo potencial. Te mostraremos cómo se compara con otras herramientas, cómo configurarlo y cómo ejecutar tus pruebas de manera efectiva. Durante la masterclass, haremos ejercicios para ayudarte a sentirte cómodo con el filtrado, el uso de afirmaciones nativas, la ejecución de pruebas en paralelo, el uso de CLI y más. También hablaremos sobre trabajar con TypeScript, hacer informes personalizados y la cobertura de código.