Registro de instantáneas de montón mediante la herramienta Memoria

Use el generador de perfiles del montón en la herramienta Memoria para hacer lo siguiente:

  • Registre instantáneas de montón de JavaScript (montón de JS).
  • Analice los gráficos de memoria.
  • Comparar instantáneas.
  • Busque pérdidas de memoria.

El generador de perfiles de montón de DevTools muestra la distribución de memoria que usan los objetos JavaScript y los nodos DOM relacionados en la página web representada.

Tomar una instantánea

  1. Abra la página web que desea analizar. Por ejemplo, abra la página de demostración Objetos dispersos en una nueva ventana o pestaña.

  2. Para abrir DevTools, haga clic con el botón derecho en la página web y, a continuación, seleccione Inspeccionar. O bien, presione Ctrl+Mayús+I (Windows, Linux) o Comando+Opción+I (macOS). Se abre DevTools.

  3. En DevTools, en la barra de actividad, seleccione la pestaña Memoria . Si esa pestaña no está visible, haga clic en el botón Más herramientas (icono Más herramientas).

  4. En la sección Seleccionar tipo de generación de perfiles , seleccione el botón de opción Instantánea de montón .

  5. En Seleccionar instancia de máquina virtual JavaScript, seleccione la máquina virtual de JavaScript de la que desea generar perfiles.

  6. Haga clic en el botón Tomar instantánea :

La herramienta Memoria, la opción Instantánea de montón está seleccionada y el botón Tomar instantánea está resaltado.

Una vez que la instantánea del montón recién registrada se ha cargado en DevTools y se ha analizado, se muestra la instantánea y aparece una nueva entrada en la barra lateral Perfiles de HEAP SNAPSHOTS:

Tamaño total de objetos accesibles

El número debajo del nuevo elemento de barra lateral muestra el tamaño total de los objetos JavaScript accesibles. Para obtener más información sobre los tamaños de objetos en la instantánea del montón, consulte Tamaños y distancias de objetos en Terminología de memoria.

La instantánea solo muestra los objetos del gráfico de memoria a los que se puede acceder desde el objeto global. La toma de una instantánea siempre comienza con una recolección de elementos no utilizados.

Tomar otra instantánea

Para tomar otra instantánea cuando ya se muestre una en la herramienta Memoria , en la barra lateral, haga clic en Perfiles encima de la instantánea existente:

Botón Perfiles para tomar otra instantánea

Borrar instantáneas

Para borrar todas las instantáneas de la herramienta Memoria , haga clic en el icono Borrar todos los perfiles (icono Borrar):

Eliminación de instantáneas

Visualización de instantáneas

Las instantáneas de montón se pueden ver de varias maneras diferentes en la herramienta Memoria . Cada forma de ver una instantánea de montón en la interfaz de usuario corresponde a una tarea diferente:

View Contenido Se usa para
Resumen Muestra objetos agrupados por su nombre de constructor. Buscar objetos y la memoria que usan, en función de los tipos que se agrupan por nombre de constructor. Útil para el seguimiento de fugas de DOM.
Comparación Muestra las diferencias entre dos instantáneas. Comparación de dos (o más) instantáneas de memoria antes y después de una operación. Inspeccionar el delta en la memoria liberada e inspeccionar el recuento de referencias le ayuda a confirmar la presencia y la causa de una pérdida de memoria, y ayuda a determinar su causa.
Contención Permite la exploración del contenido del montón. Proporciona una mejor vista de la estructura de objetos, lo que ayuda a analizar los objetos a los que se hace referencia en el espacio de nombres global (ventana) para averiguar lo que mantiene los objetos alrededor. Úsela para analizar cierres y profundizar en los objetos a un nivel bajo.

Para cambiar entre vistas, use la lista desplegable en la parte superior de la herramienta Memoria :

Cambiar selector de vistas

Nota:

No todas las propiedades se almacenan en el montón de JavaScript. Las propiedades implementadas mediante captadores que ejecutan código nativo no se capturan. Además, no se capturan valores que no sean de cadena, como números.

Vista de resumen

Inicialmente, se abre una instantánea del montón en la vista Resumen , que muestra una lista de constructores:

Vista de resumen

Cada constructor de la lista se puede expandir para mostrar los objetos que se crearon instancias mediante ese constructor.

Para cada constructor de la lista, la vista Resumen también muestra un número como ×123, que indica el número total de objetos creados con el constructor. La vista Resumen también muestra las columnas siguientes:

Nombre de columna Descripción
Distancia Muestra la distancia a la raíz mediante la ruta de acceso más corta de los nodos. Consulte Terminología de distancia en memoria.
Tamaño superficial Muestra la suma de tamaños superficiales de todos los objetos creados por una función de constructor determinada. El tamaño superficial es el tamaño del montón de JavaScript que contiene directamente un objeto. El tamaño superficial de un objeto suele ser pequeño, ya que un objeto De JavaScript a menudo solo almacena su descripción del objeto, no los valores, en la memoria que contiene directamente el objeto. La mayoría de los objetos JavaScript almacenan sus valores en un almacén de respaldo que se encuentra en otra parte del montón de JavaScript y solo exponen un pequeño objeto contenedor en la parte del montón de JavaScript que es propiedad directa del objeto. Consulte Tamaño superficial en Terminología de memoria.
Tamaño retenido Muestra el tamaño máximo retenido entre el mismo conjunto de objetos. El tamaño de la memoria que puede liberar después de eliminar un objeto (y que ya no se pueda acceder a los dependientes) se denomina tamaño retenido. Consulte Tamaño retenido en terminología de memoria.

Después de expandir un constructor en la vista Resumen , se muestran todas las instancias del constructor. Para cada instancia, los tamaños superficiales y retenidos se muestran en las columnas correspondientes. El número después del @ carácter es el identificador único del objeto, lo que permite comparar las instantáneas del montón por objeto.

Entradas del constructor en la vista Resumen

En la vista Resumen de la herramienta Memoria se enumeran los grupos de constructores de objetos:

Grupos de constructores

Los grupos de constructores de la vista Resumen pueden ser funciones integradas como Array o Object pueden ser funciones definidas en su propio código.

Para mostrar la lista de objetos a los que se ha creado una instancia de un constructor determinado, expanda el grupo de constructores.

Nombres de categoría especiales en la vista Resumen

La vista Resumen también contiene nombres de categoría especiales que no se basan en constructores. Estas categorías especiales son:

Nombre de categoría Description
(matriz) Varios objetos internos similares a una matriz que no se corresponden directamente con objetos visibles desde JavaScript, como el contenido de matrices de JavaScript o las propiedades con nombre de objetos JavaScript.
(código compilado) Datos internos que V8 (motor de JavaScript de Microsoft Edge) necesita para ejecutar funciones definidas por JavaScript o WebAssembly. V8 administra automáticamente el uso de memoria en esta categoría: si una función se ejecuta muchas veces, V8 usa más memoria para esa función para que la función se ejecute más rápido. Si una función no se ha ejecutado en un tiempo, V8 podría eliminar los datos internos de esa función.
(cadena concatenada) Cuando dos cadenas se concatenan juntas, como cuando se usa el operador JavaScript + , V8 puede optar por representar el resultado internamente como una cadena concatenada. En lugar de copiar todos los caracteres de las dos cadenas en una nueva cadena, V8 crea un objeto pequeño que apunta a las dos cadenas.
InternalNode Objetos asignados fuera de V8, como objetos de C++ definidos por Blink, el motor de representación de Microsoft Edge.
(forma de objeto) Información sobre objetos, como el número de propiedades que tienen y una referencia a sus prototipos, que V8 mantiene internamente cuando se crean y actualizan objetos. Esto permite que V8 represente de forma eficaz objetos con las mismas propiedades.
(cadena segmentada) Al crear una subcadena, como cuando se usa el método JavaScript substring , V8 puede optar por crear un objeto de cadena segmentada en lugar de copiar todos los caracteres pertinentes de la cadena original. Este nuevo objeto contiene un puntero a la cadena original y describe qué intervalo de caracteres de la cadena original se va a usar.
system/Context Variables locales desde un ámbito de JavaScript al que puede acceder alguna función anidada. Cada instancia de función contiene un puntero interno al contexto en el que se ejecuta, de modo que pueda acceder a esas variables.
(sistema) Varios objetos internos que aún no se han clasificado de forma más significativa.

Vista de comparación

Para buscar objetos filtrados, compare varias instantáneas entre sí. En una aplicación web, normalmente, realizar una acción y, a continuación, la acción inversa no debería dar lugar a más objetos en la memoria. Por ejemplo, al abrir un documento y, a continuación, cerrarlo, el número de objetos en memoria debe ser el mismo que antes de abrir el documento.

Para comprobar que ciertas operaciones no crean pérdidas:

  1. Tome una instantánea del montón antes de realizar una operación.

  2. Realice la operación. Es decir, interactuar con la página de alguna manera que podría estar causando una fuga.

  3. Realice la operación inversa. Es decir, hacer la interacción opuesta y repetirla varias veces.

  4. Tome una segunda instantánea del montón.

  5. En la segunda instantánea del montón, cambie la vista a Comparación y compárela con la instantánea 1.

En la vista Comparación , se muestra la diferencia entre dos instantáneas:

Vista de comparación

Al expandir un constructor en la lista, se muestran las instancias de objeto agregadas y eliminadas.

Vista de contención

La vista Contención permite ver dentro de los cierres de función, observar objetos internos de máquina virtual (VM) que componen los objetos de JavaScript y comprender cuánta memoria usa la aplicación en un nivel muy bajo:

Vista de contención

La vista Contención muestra los siguientes tipos de objetos:

Puntos de entrada de la vista de contención Description
Objetos DOMWindow Objetos globales para código JavaScript.
Raíces de GC Raíces de GC usadas por el recolector de elementos no utilizados de la máquina virtual JavaScript. Las raíces de GC se componen de mapas de objetos integrados, tablas de símbolos, pilas de subprocesos de máquina virtual, cachés de compilación, ámbitos de identificador y identificadores globales.
Objetos nativos Objetos creados por el explorador, como nodos DOM y reglas CSS, que se muestran en la máquina virtual JavaScript para permitir la automatización.

Sección Retenedores

La sección Retenedores se muestra en la parte inferior de la herramienta Memoria y muestra todos los objetos que apuntan al objeto seleccionado. La sección Retenedores se actualiza al seleccionar un objeto diferente en la vista Resumen, Contención o Comparación .

En la captura de pantalla siguiente, se seleccionó un objeto de cadena en la vista Resumen y la sección Retainers muestra que la cadena se conserva mediante la x propiedad de una instancia de la Item clase , que se encuentra en el example-03.js archivo :

Sección Retenedores

Ocultar ciclos

En la sección Retenes , al analizar los objetos que conservan el objeto seleccionado, es posible que encuentre ciclos. Los ciclos se producen cuando el mismo objeto aparece más de una vez en la ruta de acceso del retención del objeto seleccionado. En la sección Retenedores , se indica que un objeto con ciclo está atenuado.

Para simplificar la ruta de acceso del retenedor, oculte los ciclos en la sección Retenedores haciendo clic en el menú desplegable Filtrar bordes y, a continuación, seleccionando Ocultar ciclo:

El menú desplegable Filtrar bordes de la sección Retenedores,

Ocultar nodos internos

Los nodos internos son objetos específicos de V8 (el motor de JavaScript en Microsoft Edge).

Para ocultar los nodos internos de la sección Retenedores , en el menú desplegable Bordes de filtro , seleccione Ocultar interno.

Configuración de la columna Tamaño superficial para incluir el tamaño de un objeto completo

De forma predeterminada, la columna Tamaño superficial de la herramienta Memoria solo incluye el tamaño del propio objeto. El tamaño superficial es el tamaño del montón de JavaScript que contiene directamente un objeto. El tamaño superficial de un objeto suele ser pequeño, ya que un objeto De JavaScript a menudo solo almacena su descripción del objeto, no los valores, en la memoria que contiene directamente el objeto. La mayoría de los objetos JavaScript almacenan sus valores en un almacén de respaldo que se encuentra en otra parte del montón de JavaScript y solo exponen un pequeño objeto contenedor en la parte del montón de JavaScript que es propiedad directa del objeto. Por ejemplo, las instancias de JavaScript Array almacenan el contenido de la matriz en un almacén de respaldo, que es una ubicación de memoria independiente que no se incluye en el tamaño superficial de la matriz.

A partir de Microsoft Edge 123, puede configurar la columna Tamaño superficial para informar del tamaño completo de los objetos, incluido el tamaño del almacén de respaldo del objeto.

Para incluir el tamaño completo de los objetos en la columna Tamaño superficial :

  1. En DevTools, haga clic en el botón Personalizar y controlar DevTools (personalizar y controlar DevTools) y, a continuación, haga clic en Configuración (icono Configuración). O bien, mientras DevTools tiene el foco, presione F1.

  2. En la sección Experimentos , active la casilla En instantáneas de montón, trate el tamaño del almacén de respaldo como parte del objeto contenedor.

  3. Haga clic en el botón Cerrar (x) de la página Configuración y, a continuación, haga clic en el botón Volver a cargar DevTools .

  4. Tome una nueva instantánea del montón. La columna Tamaño superficial ahora incluye el tamaño completo de los objetos:

    Columna Tamaño superficial de una instantánea de montón

Filtrar instantáneas de montón por tipos de nodo

Use filtros para centrarse en partes específicas de una instantánea de montón. Al examinar todos los objetos de una instantánea de montón en la herramienta Memoria , puede ser difícil centrarse en objetos específicos o conservar rutas de acceso.

Para centrarse solo en tipos específicos de nodos, use el filtro Tipos de nodo , en la esquina superior derecha. Por ejemplo, para ver solo las matrices y los objetos de cadena en la instantánea del montón:

  1. Para abrir el filtro Tipos de nodo , haga clic en Predeterminado en la esquina superior derecha.

  2. Seleccione las entradas Matriz y Cadena .

    La instantánea del montón se actualiza para mostrar solo los objetos de matriz y cadena:

    Tipos de nodo en una instantánea de montón en la herramienta Memoria

Búsqueda de un objeto específico

Para buscar un objeto en el montón recopilado, puede buscar mediante Ctrl+F y proporcionar el identificador de objeto.

Descubrir fugas de DOM

La herramienta Memoria tiene la capacidad de mostrar las dependencias bidireccionales que a veces existen entre objetos nativos del explorador (nodos DOM, reglas CSS) y objetos JavaScript. Esto ayuda a detectar fugas de memoria que se producen debido a nodos DOM separados olvidados que permanecen en la memoria.

Tenga en cuenta el siguiente árbol DOM:

Subárboles DOM

En el ejemplo de código siguiente se crean las variables treeRef de JavaScript y leafRef, que hacen referencia a dos de los nodos DOM del árbol:

// Get a reference to the #tree element.
const treeRef = document.querySelector("#tree");

// Get a reference to the #leaf element,
// which is a descendant of the #tree element.
const leafRef = document.querySelector("#leaf");

En el ejemplo de código siguiente, el <div id="tree"> elemento se quita del árbol DOM:

// Remove the #tree element from the DOM.
document.body.removeChild(treeRef);

El <div id="tree"> elemento no se puede recopilar como elemento no utilizado porque la variable treeRef de JavaScript todavía existe. La treeRef variable hace referencia directamente al <div id="tree"> elemento . En el ejemplo de código siguiente, se nullifica la treeRef variable:

// Remove the treeRef variable.
treeRef = null;

El <div id="tree"> elemento todavía no se puede recopilar como elemento no utilizado porque la variable leafRef de JavaScript todavía existe. La leafRef.parentNode propiedad hace referencia al <div id="tree"> elemento . En el ejemplo de código siguiente, se nullifica la leafRef variable:

// Remove the leafRef variable.
leafRef = null;

En este punto, el <div id="tree"> elemento puede ser recolector de elementos no utilizados. En treeRef primer lugar, y leafRef deben anularse, para que todo el árbol DOM del <div id="tree"> elemento se recopile como elementos no utilizados.

Página web de demostración: Ejemplo 6: Fuga de nodos DOM

Para comprender dónde se pueden filtrar los nodos DOM y cómo detectar dicha pérdida, abra la página web de ejemplo Ejemplo 6: Fuga de nodos DOM en una nueva ventana o pestaña.

Página web de demostración: ejemplo 9: fugas dom mayores de lo esperado

Para ver por qué una fuga dom podría ser mayor de lo esperado, abra la página web de ejemplo Ejemplo 9: Fugas dom mayores de lo esperado en una nueva ventana o pestaña.

Análisis del impacto de los cierres en la memoria

Para analizar el impacto de los cierres en la memoria, pruebe este ejemplo:

  1. Abra la página web de demostración de Eval is evil en una nueva ventana o pestaña.

  2. Registre una instantánea del montón.

  3. En la página web representada, haga clic en el botón Cierres con eval .

  4. Registre una segunda instantánea del montón.

    En la barra lateral, el número debajo de la segunda instantánea debe ser mayor que el número debajo de la primera instantánea. Esto indica que la página web usa más memoria después de hacer clic en el botón Cierres con eval .

  5. En la segunda instantánea del montón, cambie la vista a Comparación y, a continuación, compare la segunda instantánea del montón con la primera instantánea del montón.

    La vista Comparación muestra que se crearon nuevas cadenas en la segunda instantánea del montón:

    La vista Comparación, que muestra que se crearon nuevas cadenas en la segunda instantánea

  6. En la vista Comparación, expanda el constructor (cadena).

  7. Haga clic en la primera entrada (cadena).

    La sección Retainers se actualiza y muestra que la largeStr variable conserva la cadena seleccionada en la vista Comparación .

    La largeStr entrada se expande automáticamente y muestra que la función conserva la eC variable, que es el cierre donde se define la variable:

    Sección Retainers, que muestra que la función eC conserva la cadena.

Sugerencia: Funciones de nombre para diferenciar entre cierres en una instantánea

Para distinguir fácilmente entre cierres de JavaScript en una instantánea de montón, proporcione los nombres de las funciones.

En el ejemplo siguiente se usa una función sin nombre para devolver la largeStr variable :

function createLargeClosure() {
    const largeStr = 'x'.repeat(1000000).toLowerCase();

    // This function is unnamed.
    const lC = function() {
        return largeStr;
    };

    return lC;
}

En el ejemplo siguiente se asigna un nombre a la función, lo que facilita la distinción entre cierres en la instantánea del montón:

function createLargeClosure() {
    const largeStr = 'x'.repeat(1000000).toLowerCase();

    // This function is named.
    const lC = function lC() {
        return largeStr;
    };

    return lC;
}

Guardar y exportar cadenas desde una instantánea de montón a JSON

Al tomar una instantánea de montón en la herramienta Memoria , puede exportar todos los objetos de cadena de la instantánea a un archivo JSON. En la herramienta Memoria , en la sección Constructor , haga clic en el botón Guardar todo en archivo situado junto a la (string) entrada:

Guardar todas las cadenas de una instantánea de montón en JSON

La herramienta Memoria exporta un archivo JSON que contiene todos los objetos de cadena de la instantánea del montón:

Cadenas de la instantánea del montón, en el archivo JSON

Consulte también

Nota:

Las partes de esta página son modificaciones basadas en el trabajo creado y compartido por Google y usadas según los términos descritos en la licencia internacional creative Commons Attribution 4.0. La página original se encuentra aquí y está creada por Meggin Kearney (Escritor técnico).

Licencia de Creative Commons Esta obra está licenciada bajo una Licencia Internacional Creative Commons Attribution 4.0.