Solucionar problemas de memoria

Obtenga información sobre cómo usar Microsoft Edge y DevTools para buscar problemas de memoria que afecten al rendimiento de la página, incluidas las pérdidas de memoria, la saturación de memoria y las recolecciones frecuentes de elementos no utilizados.

  • Descubra la cantidad de memoria que la página usa actualmente con el Administrador de tareas del explorador Microsoft Edge.
  • Visualice el uso de memoria con el tiempo con la herramienta Memoria .
  • Identifique los árboles DOM desasociados (una causa común de pérdidas de memoria) con la instantánea del montón.
  • Averigüe cuándo se asigna nueva memoria en el montón de JavaScript (montón de JS) con instrumentación de asignación en la escala de tiempo.

Consulte también Depurar pérdidas de memoria DOM con la herramienta Elementos desasociados.

Introducción

En el espíritu del modelo de rendimiento RAIL , el foco de los esfuerzos de rendimiento deben ser los usuarios.

Los problemas de memoria son importantes porque los usuarios suelen percibirlos. Los usuarios pueden percibir problemas de memoria de las siguientes maneras:

  • El rendimiento de una página empeora progresivamente con el tiempo. Posiblemente se trata de un síntoma de pérdida de memoria. Una pérdida de memoria se produce cuando un error en la página hace que la página use progresivamente más y más memoria con el tiempo.

  • El rendimiento de una página es constantemente malo. Este es posiblemente un síntoma de hinchazón de memoria. La saturación de memoria se produce cuando una página usa más memoria de la necesaria para una velocidad de página óptima.

  • El rendimiento de una página se retrasa o parece pausarse con frecuencia. Este es posiblemente un síntoma de recolecciones de elementos no utilizados frecuentes. La recolección de elementos no utilizados es cuando el explorador reclama memoria. El explorador decide cuándo ocurre esto. Durante las colecciones, todo el script que se ejecuta está en pausa. Por lo tanto, si el explorador está recogiendo mucho elementos no utilizados, el tiempo de ejecución del script se va a pausar mucho.

Hinchazón de memoria: ¿cuánto es "demasiado"?

Una pérdida de memoria es fácil de definir. Si un sitio usa progresivamente más y más memoria, tiene una pérdida. Pero el exceso de memoria es un poco más difícil de anclar. ¿Qué califica como "usar demasiada memoria"?

Aquí no hay números duros, ya que los diferentes dispositivos y exploradores tienen diferentes funcionalidades. La misma página que se ejecuta sin problemas en un smartphone de gama alta puede bloquearse en un smartphone de gama baja.

La clave aquí es usar el modelo RAIL y centrarse en los usuarios. Averigüe qué dispositivos son populares entre los usuarios y, a continuación, pruebe la página en esos dispositivos. Si la experiencia es constantemente incorrecta, es posible que la página supere las capacidades de memoria de esos dispositivos.

Supervisión del uso de memoria en tiempo real con el Administrador de tareas del explorador Microsoft Edge

Use el Administrador de tareas del explorador Microsoft Edge como punto de partida para la investigación de problemas de memoria. El Administrador de tareas del explorador Microsoft Edge es un monitor en tiempo real que le indica cuánta memoria está usando actualmente una página.

  1. Presione Mayús+Esc o vaya al menú principal de Microsoft Edge y seleccione Más herramientasAdministrador de tareas >del explorador para abrir el Administrador de tareas del explorador Microsoft Edge.

    Apertura del Administrador de tareas del explorador Microsoft Edge

  2. Haga clic con el botón derecho en el encabezado de tabla del Administrador de tareas del explorador Microsoft Edge y, a continuación, habilite la memoria de JavaScript.

    Habilitación de la memoria de JavaScript

Estas dos columnas le indican cosas diferentes sobre cómo usa la memoria la página:

  • La columna Memoria representa la memoria nativa. Los nodos DOM se almacenan en memoria nativa. Si este valor aumenta, se crean nodos DOM.

  • La columna Memoria de JavaScript representa el montón de JS. Esta columna contiene dos valores. El valor que le interesa es el número dinámico (el número entre paréntesis). El número dinámico representa la cantidad de memoria que usan los objetos accesibles de la página. Si este número aumenta, se crean nuevos objetos o los objetos existentes están creciendo.

Visualización de pérdidas de memoria con la herramienta Rendimiento

También puede usar la herramienta Rendimiento como otro punto de partida en la investigación. La herramienta Rendimiento le ayuda a visualizar el uso de memoria de una página a lo largo del tiempo.

  1. En DevTools, abra la herramienta Rendimiento .

  2. Active la casilla Memoria .

  3. Haga una grabación.

Es una buena práctica iniciar y finalizar la grabación con una recolección de elementos no utilizados forzada. Para forzar la recolección de elementos no utilizados, haga clic en el botón Recopilarrecolección de elementos no utilizados durante la grabación.

Para mostrar las grabaciones de memoria, tenga en cuenta el código siguiente:

var x = [];
function grow() {
    for (var i = 0; i < 10000; i++) {
        document.body.appendChild(document.createElement('div'));
    }
    x.push(new Array(1000000).join('x'));
}
document.getElementById('grow').addEventListener('click', grow);

Cada vez que se hace clic en el botón al que se hace referencia en el código, se anexan 10 000 div nodos al cuerpo del documento y se inserta una cadena de 1000 000 x caracteres en la x matriz. La ejecución del ejemplo de código anterior genera una grabación en la herramienta Rendimiento como la siguiente ilustración:

Crecimiento simple

En primer lugar, una explicación de la interfaz de usuario. El gráfico MONTÓN del panel Información general (debajo de NET) representa el montón de JS. Debajo del panel Información general se encuentra el panel Contador . El uso de memoria se desglosa mediante el montón de JS (igual que el gráfico HEAP en el panel Información general ), documentos, nodos DOM, agentes de escucha y memoria de GPU. Desactive una casilla para ocultarla del gráfico.

Ahora, un análisis del código en comparación con la ilustración anterior. Si revisa el contador de nodos (el gráfico verde), coincide correctamente con el código. El recuento de nodos aumenta en pasos discretos. Puede suponer que cada aumento en el número de nodos es una llamada a grow().

El gráfico del montón JS (el gráfico azul) no es tan sencillo. De acuerdo con los procedimientos recomendados, el primer descenso es realmente una recolección de elementos no utilizados forzada (haga clic en el botón Recopilar recolección de elementos no utilizados).

A medida que avanza la grabación, se muestran los picos de tamaño del montón js. Esto es natural y esperado: el código JavaScript está creando los nodos DOM en cada botón en el que haga clic y está haciendo mucho trabajo cuando crea la cadena de un millón de caracteres.

Lo clave aquí es el hecho de que el montón de JS termina más alto de lo que comenzó (el "principio" aquí es el punto después de la recolección de elementos no utilizados forzados). En el mundo real, si viera este patrón de aumento del tamaño del montón js o el tamaño del nodo, podría indicar una pérdida de memoria.

Detección de pérdidas de memoria de árbol DOM desasociadas con instantáneas de montón

Un nodo DOM solo se recopila cuando no hay referencias al nodo desde el árbol DOM o el código JavaScript que se ejecuta en la página. Se dice que un nodo está "desasociado" cuando se quita del árbol DOM, pero algunos JavaScript siguen haciendo referencia a él. Los nodos DOM desasociados son una causa común de pérdidas de memoria.

En esta sección se explica cómo usar los generadores de perfiles de montón en DevTools para identificar nodos desasociados.

Este es un ejemplo sencillo de nodos DOM desasociados:

var detachedTree;

function create() {
    var ul = document.createElement('ul');
    for (var i = 0; i < 10; i++) {
        var li = document.createElement('li');
        ul.appendChild(li);
    }
    detachedTree = ul;
}
document.getElementById('create').addEventListener('click', create);

Al hacer clic en el botón al que se hace referencia en el código, se crea un ul nodo con diez li elementos secundarios. El código hace referencia a los nodos, pero no existen en el árbol DOM, por lo que cada nodo se desasocia.

Las instantáneas de montón son una manera de identificar nodos desasociados. Como su nombre indica, las instantáneas del montón muestran cómo se distribuye la memoria entre los objetos JS y los nodos DOM de la página en el momento de la instantánea.

Para crear una instantánea:

  1. Abra DevTools y vaya a la herramienta Memoria .

  2. Haga clic en el botón de radio Instantánea de montón y, a continuación, haga clic en el botón Tomar instantánea en la parte inferior de la herramienta.

    Tomar una instantánea del montón

    La instantánea puede tardar algún tiempo en procesarse y cargarse.

  3. Una vez finalizada la instantánea, selecciónela en el panel izquierdo (se denomina HEAP SNAPSHOTS).

  4. En el cuadro de texto Filtro de clase , escriba Detached, para buscar árboles DOM separados:

    Filtrado de nodos desasociados

  5. Expanda los quilates para investigar un árbol desasociado:

    Investigación del árbol desasociado

  6. Haga clic en un nodo para investigarlo más.

    En el panel Objetos , puede ver más información sobre el código que hace referencia al nodo. Por ejemplo, en la ilustración siguiente, la detachedTree variable hace referencia al nodo.

  7. Para corregir la pérdida de memoria determinada, estudiar el código que usa la detachedTree variable y asegurarse de que la referencia al nodo se quita cuando ya no se necesita.

Investigación de un nodo

Identificación de pérdidas de memoria del montón js con instrumentación de asignación en la escala de tiempo

La instrumentación de asignación en la escala de tiempo es otra herramienta que puede ayudarle a realizar un seguimiento de las pérdidas de memoria en el montón de JS.

Muestre la instrumentación de asignación en la escala de tiempo mediante el código siguiente:

var x = [];
function grow() {
    x.push(new Array(1000000).join('x'));
}
document.getElementById('grow').addEventListener('click', grow);

Cada vez que se hace clic en el botón al que se hace referencia en el código, se agrega una cadena de un millón de caracteres a la x matriz.

Para registrar una instrumentación de asignación en la escala de tiempo:

  1. Abra DevTools y seleccione la herramienta Memoria .

  2. Haga clic en el botón de radio Instrumentación de asignación en la escala de tiempo y, a continuación, haga clic en el botón Inicio .

  3. Realice la acción que sospeche que está causando la pérdida de memoria.

  4. Cuando haya terminado, haga clic en el botón Detener grabación del perfil del montóndetener grabación .

  5. Mientras graba, observe si se muestran barras azules en la instrumentación de asignación en la escala de tiempo, como en la ilustración siguiente:

    Nuevas asignaciones

    Esas barras azules representan nuevas asignaciones de memoria. Esas nuevas asignaciones de memoria son las candidatas para pérdidas de memoria.

  6. Acercar una barra para filtrar el panel Constructor para mostrar solo los objetos asignados durante el período de tiempo especificado.

    Escala de tiempo de asignación ampliada

  7. Expanda el objeto y seleccione el valor para ver más detalles en el panel Objeto .

    Por ejemplo, en la ilustración siguiente, en los detalles del objeto recién asignado indica que se asignó a la x variable en el Window ámbito:

Detalles del objeto

Investigación de la asignación de memoria por función

Use el tipo de generación de perfiles De muestreo de asignación para ver la asignación de memoria por función JavaScript.

Muestreo de asignación de registros

  1. Haga clic en el botón de radio Muestreo de asignación .

  2. Si hay un trabajo en la página, puede seleccionarlo como destino de generación de perfiles mediante el menú desplegable situado junto al botón Inicio .

  3. Haga clic en el botón Inicio .

  4. En la página web, realice las acciones que quiera investigar.

  5. Haga clic en el botón Detener cuando haya terminado todas las acciones.

DevTools muestra un desglose de la asignación de memoria por función. La vista predeterminada es Heavy (abajo arriba), que muestra las funciones que asignaron la mayor cantidad de memoria en la parte superior.

Muestreo de asignación

Reducción de elementos no utilizados con opciones adicionales para el muestreo de asignación

De forma predeterminada, el tipo de generación de perfiles de muestreo de asignación solo notifica las asignaciones que siguen activas al final de la sesión de grabación. Los objetos creados, quitados y, a continuación, recolector de elementos no utilizados (GC'd) no se muestran en la herramienta Memoria al generar perfiles mediante el muestreo de asignación o la instrumentación de asignación en los tipos de escala de tiempo.

Puede confiar en el explorador para limpiar elementos no utilizados del código. Sin embargo, es importante tener en cuenta que gc en sí es una operación costosa y varios GCs pueden ralentizar la experiencia del usuario de su sitio web o aplicación. Al grabar en la herramienta Rendimiento con la casilla Memoria activada, puede ver que la operación gc se produce en los acantilados empinados (disminuciones repentinas) del gráfico del montón.

Operación gc que se muestra en la herramienta Rendimiento

Al reducir la cantidad de elementos no utilizados que está creando el código, puede reducir el costo de cada GC individual y el número de operaciones de GC. Para realizar un seguimiento de los objetos descartados por GC, configure el tipo de generación de perfiles de muestreo de asignación con valores.

  1. Haga clic en el botón De muestreo de asignación .

  2. Haga clic en incluir objetos descartados por gc principal e incluir objetos descartados por la configuración de GC secundaria .

    Configuración de GC de muestreo de asignación

  3. Haga clic en el botón Inicio .

  4. En la página web, realice las acciones que quiera investigar.

  5. Haga clic en el botón Detener cuando haya terminado todas las acciones.

DevTools ahora realiza un seguimiento de todos los objetos que fueron GC'd durante la grabación. Use esta configuración para comprender la cantidad de elementos no utilizados que genera el sitio web o la aplicación. Los datos notificados por el muestreo de asignación le ayudarán a identificar las funciones que generan más elementos no utilizados.

Si está investigando objetos que solo eran GC'd durante operaciones de GC principales o secundarias específicas, configure los valores adecuadamente para realizar un seguimiento de la operación que le interesa. Para obtener más información sobre las diferencias entre gc principal y menor, vea Trash talk: the Orinoco garbage collector | Blog para desarrolladores del motor de JavaScript V8.

Detectar recolecciones de elementos no utilizados frecuentes

Si la página parece pausarse con frecuencia, es posible que tenga problemas de recolección de elementos no utilizados.

Puede usar el Administrador de tareas del explorador Microsoft Edge o las grabaciones de memoria de rendimiento para detectar la recolección de elementos no utilizados frecuentes.

  • En el Administrador de tareas del explorador Microsoft Edge, los valores de memoria o memoria de JavaScript que aumentan y caen con frecuencia representan la recolección de elementos no utilizados frecuentes.

  • En las grabaciones de rendimiento, los cambios frecuentes (aumento y caída) en los gráficos de recuento de nodos o montón de JS indican una recolección frecuente de elementos no utilizados.

Una vez identificado el problema, puede usar una instrumentación de asignación en la grabación de escala de tiempo para averiguar dónde se asigna memoria y qué funciones están causando las asignaciones.

Nota

Algunas partes de esta página son modificaciones basadas en el trabajo creado y compartido por Google y se usan según los términos descritos en la Licencia internacional de Creative Commons Attribution 4.0. La página original se encuentra aquí y está creada por Kayce Basques (Technical Writer, Chrome DevTools & Lighthouse).

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