Supervisión de toda la memoria utilizada por una página web: performance.measureMemory ()

El autor del artículo, cuya traducción publicamos hoy, habla sobre cómo monitorear la memoria asignada a las páginas web. La atención cuidadosa a la memoria de las páginas que trabajan en producción ayuda a mantener la productividad de los proyectos web a un alto nivel.



Los navegadores controlan automáticamente la memoria asignada a las páginas web. Cuando una página crea un objeto, el navegador, utilizando sus mecanismos internos, asigna memoria para almacenar este objeto. Como la memoria no es un recurso infinito, el navegador realiza periódicamente la recolección de basura, durante la cual se detectan objetos innecesarios y se borra la memoria que ocupan. El proceso de detección de tales objetos, sin embargo, no es ideal. Ha sido probadoque la identificación absolutamente precisa y completa de tales objetos es una tarea insoluble. Como resultado, los navegadores están reemplazando la idea de encontrar "objetos innecesarios" con la idea de encontrar "objetos inalcanzables". Si una página web no puede acceder al objeto a través de las variables que tiene y los campos de otros objetos accesibles, esto significa que el navegador puede borrar con seguridad la memoria ocupada por dicho objeto. La diferencia entre "innecesario" e "inalcanzable" conduce a pérdidas de memoria, como se ilustra en el siguiente ejemplo:

const object = { a: new Array(1000), b: new Array(2000) };
setInterval(() => console.log(object.a), 1000);

Aquí hay una gran matriz innecesaria b, pero el navegador no libera la memoria que ocupa debido al hecho de que es accesible a través de la propiedad del objeto object.ben la devolución de llamada. Como resultado, la memoria ocupada por esta matriz tiene fugas.

Las pérdidas de memoria son frecuentes en el desarrollo web. Aparecen muy fácilmente en programas cuando, por ejemplo, los desarrolladores olvidan darse de baja del detector de eventos, cuando capturan accidentalmente objetos en un elemento iframe, cuando olvidan cerrar al trabajador, cuando recolectan objetos en matrices. Si una página web tiene pérdidas de memoria, esto lleva al hecho de que con el tiempo aumenta el consumo de memoria de la página. Tal página parece lenta y lenta para los usuarios.

El primer paso para resolver este problema es tomar medidas. La nueva API performance.measureMemory () permite a los desarrolladores medir el uso de memoria de las páginas web en producción y, como resultado, detectar pérdidas de memoria que se escapan a través de pruebas locales.

¿En qué se diferencia la nueva API performance.measureMemory () de la antigua performance.memory?


Si está familiarizado con la API no estándar existente performance.memory, es posible que le interese la cuestión de cómo la nueva API difiere de la anterior. La principal diferencia es que la API anterior devuelve el tamaño del montón de JavaScript, y la nueva evalúa el uso de memoria de toda la página web. Esta distinción es importante cuando Chrome organiza el uso compartido del montón entre varias páginas web (o varias instancias de la misma página). En tales casos, los resultados devueltos por la antigua API pueden estar distorsionados. Dado que la antigua API se define en términos específicos de la implementación, como un montón, estandarizarla es un negocio desesperado.

Otra diferencia es que en Chrome, la nueva API toma medidas de memoria al recolectar basura. Esto reduce el "ruido" en los resultados de la medición, pero puede tomar algún tiempo obtener los resultados. Tenga en cuenta que los creadores de otros navegadores pueden decidir implementar la nueva API sin vincularse a la recolección de basura.

Formas recomendadas de usar la nueva API


El uso de la memoria por parte de las páginas web depende de la ocurrencia de eventos, acciones del usuario, recolección de basura. Es por eso que la API está performance.measureMemory()diseñada para estudiar el nivel de uso de memoria en la producción. Los resultados de llamar a esta API en un entorno de prueba son menos útiles. Aquí hay ejemplos de opciones para usarlo:

  • - .
  • A/B- , .
  • .
  • , . .


Actualmente, la API en cuestión solo es compatible con Chrome 83, de acuerdo con el esquema Origin Trial. Los resultados devueltos por la API dependen en gran medida de la implementación, ya que diferentes navegadores utilizan diferentes formas de representar objetos en la memoria y diferentes formas de evaluar el nivel de uso de la memoria. Los navegadores pueden excluir algunas áreas de la memoria de la contabilidad si la contabilidad completa de toda la memoria utilizada es una tarea excesivamente difícil o imposible. Como resultado, podemos decir que los resultados producidos por esta API en diferentes navegadores no son comparables. Tiene sentido comparar solo los resultados obtenidos en el mismo navegador.

Progreso laboral actual


Pasocondición
1. Crear explicaciones de API
Terminado
2. Crear un borrador de especificación
Realizado
3. Recopilación de comentarios y finalización del proyecto.
Realizado
4. Pruebas de prueba de origen
Realizado
5. Lanzamiento
No empezado

Usando performance.measureMemory ()


▍ Habilitar el soporte de prueba de Origin


La API performance.measureMemory()está disponible en Chrome 83 de acuerdo con el esquema Origin Trial. Se espera que esta fase finalice con el lanzamiento de Chrome 84.

El programa Origin Trial permite a los desarrolladores aprovechar las nuevas funciones de Chrome y compartir comentarios sobre la conveniencia, usabilidad y efectividad de estas funciones con la comunidad web. Los detalles sobre este programa se pueden encontrar aquí . Puede suscribirse al programa en la página de registro.

▍Registro en el programa Origin Trial


  1. Solicite un token para la oportunidad que le interesa.
  2. Agregue el token a las páginas del proyecto piloto. Hay 2 formas de hacer esto:

    • Agregue una <meta>etiqueta origin-trialal título de cada página. Por ejemplo, podría tener este aspecto: <meta http-equiv="origin-trial" content="TOKEN_GOES_HERE">.
    • Si tiene acceso a la configuración del servidor, puede agregar un token utilizando un encabezado HTTP Origin-Trial. Como resultado, la cabecera de respuesta debería aparecer algo como lo siguiente: Origin-Trial: TOKEN_GOES_HERE.

▍Habilitar una nueva función a través de las banderas de Chrome


Con el fin de experimentar con performance.measureMemory(), prescindiendo de la ficha Origen de prueba, es necesario tener la bandera #experimental-web-platform-featuresen chrome://flags.

▍Verificación del uso de la API


Una llamada de función performance.measureMemory()puede fallar, con un SecurityError arrojado . Esto puede suceder si el entorno no cumple con los requisitos de seguridad para las filtraciones de información. Durante la prueba de Origin Trial en Chrome, esta API requiere la inclusión del aislamiento del sitio . Cuando la API esté lista para su uso normal, dependerá de la propiedad crossOriginIsolated . Una página web puede funcionar en este modo configurando los encabezados COOP y COEP .

Aquí hay un código de muestra:

if (performance.measureMemory) {
  let result;
  try {
    result = await performance.measureMemory();
  } catch (error) {
    if (error instanceof DOMException &&
        error.name === "SecurityError") {
      console.log("The context is not secure.");
    } else {
      throw error;
    }
  }
  console.log(result);
}

▍ Pruebas locales


Chrome toma una medida de memoria cuando recolecta basura. Esto significa que acceder a la API no resuelve instantáneamente la promesa. Para obtener el resultado, debe esperar la próxima sesión de recolección de basura. La API inicia forzosamente la recolección de basura después de un cierto tiempo de espera, que actualmente está configurado en 20 segundos. Si ejecuta Chrome con un indicador de línea de comando --enable-blink-features='ForceEagerMeasureMemory', el tiempo de espera se reducirá a cero, lo que es útil para la depuración local y las pruebas locales.

Ejemplo


Se recomienda que utilice la nueva API definiendo un monitor de memoria global que mida el nivel de uso de memoria de toda la página y envíe los resultados al servidor, donde se pueden agregar y analizar. La forma más fácil de trabajar con esta API es tomar mediciones periódicas. Por ejemplo, pueden correr cada Mminuto. Sin embargo, esto introduce distorsiones en los datos, ya que pueden producirse picos en el uso de la memoria entre las mediciones. El siguiente ejemplo demuestra cómo, utilizando el proceso de Poisson , hacer mediciones sin errores sistemáticos. Este enfoque garantiza que las sesiones de medición pueden, con la misma probabilidad, ocurrir en cualquier momento ( aquí hay una demostración de este enfoque,Aquí está el código fuente).

Primero, declare una función que planifique el próximo inicio de una sesión para medir la cantidad de memoria consumida utilizando una función setTimeout()con un intervalo establecido aleatoriamente. Se debe llamar a esta función después de cargar la página en la ventana del navegador.

function scheduleMeasurement() {
  if (!performance.measureMemory) {
    console.log("performance.measureMemory() is not available.");
    return;
  }
  const interval = measurementInterval();
  console.log("Scheduling memory measurement in " +
      Math.round(interval / 1000) + " seconds.");
  setTimeout(performMeasurement, interval);
}

//       .
window.onload = function () {
  scheduleMeasurement();
}

La función measurementInterval()encuentra un intervalo aleatorio, expresado en milisegundos, configurado de tal manera que se realice una medición aproximadamente cada cinco minutos. Si está interesado en los conceptos matemáticos en los que se basa esta función, lea sobre la distribución exponencial .

function measurementInterval() {
  const MEAN_INTERVAL_IN_MS = 5 * 60 * 1000;
  return -Math.log(Math.random()) * MEAN_INTERVAL_IN_MS;
}

Como resultado, la función asincrónica performMeasurement()llama a nuestra API, registra el resultado y planifica la próxima medición.

async function performMeasurement() {
  // 1.  performance.measureMemory().
  let result;
  try {
    result = await performance.measureMemory();
  } catch (error) {
    if (error instanceof DOMException &&
        error.name === "SecurityError") {
      console.log("The context is not secure.");
      return;
    }
    //    .
    throw error;
  }
  // 2.  .
  console.log("Memory usage:", result);
  // 3.   .
  scheduleMeasurement();
}

Los resultados de la medición pueden verse así:

// ,    :
{
  bytes: 60_000_000,
  breakdown: [
    {
      bytes: 40_000_000,
      attribution: ["https://foo.com"],
      userAgentSpecificTypes: ["Window", "JS"]
    },
    {
      bytes: 20_000_000,
      attribution: ["https://foo.com/iframe"],
      userAgentSpecificTypes: ["Window", "JS"]
    }
  ]
}

En el campo se muestra una estimación del nivel general de uso de memoria bytes. Al derivar esta estimación, se utilizan los separadores de los dígitos de los números. Estos valores dependen mucho de la implementación. Si se reciben para diferentes navegadores, entonces no puede compararlos. La forma en que se obtienen puede variar incluso en diferentes versiones del mismo navegador. Mientras dure el programa Origin Trial, los valores de retorno incluyen indicadores del uso de memoria JavaScript por la ventana principal, indicadores del uso de memoria de elementos iframedel mismo sitio e indicadores de ventanas relacionadas. Cuando la API esté lista, este valor representará información sobre la memoria consumida por JavaScript, el DOM, todos los elementos iframeasociados con Windows y los trabajadores web.

Listabreakdownda información más detallada sobre la memoria utilizada. Cada entrada describe un fragmento de memoria y asocia este fragmento con un conjunto de ventanas, elementos iframeo trabajadores identificados por una URL. El campo userAgentSpecificTypesenumera los tipos de memoria determinados por las características de implementación.

Es importante tener en cuenta estas listas de manera general y no intentar, basándose en las características de un navegador determinado, analizar todo en función de ellas. Por ejemplo, algunos navegadores pueden devolver una lista breakdownvacía o campos vacíos attribution. Otros navegadores pueden devolver attributionmúltiples URL en un elemento , lo que indica que no pueden identificar a cuál de estas URL pertenece la memoria.

Retroalimentación


El Web Performance Community Group y el equipo de desarrollo de Chrome estarán encantados de saber lo que piensas performance.measureMemory()y conocer tu experiencia con esta API.

Comparta sus ideas sobre el dispositivo API con nosotros


¿Hay algo en esta API que no funciona como se esperaba? ¿Tal vez le falta algo que necesita para implementar su idea? Abra una nueva tarea en el rastreador de proyectos o comente una tarea existente.

Informar un problema de implementación


¿Encontró un error en su implementación de Chrome? ¿O tal vez resultó que la implementación es diferente de la especificación? Registre el error aquí: new.crbug.com . Intente incluir tantos detalles como sea posible en su mensaje, incluya instrucciones simples sobre cómo reproducir el error e indique que el problema está relacionado Blink>PerformanceAPIs. Glitch es una muy buena manera de demostrar errores .

Apoyanos


performance.measureMemory()¿Estás planeando usar ? Si es así, cuéntanoslo. Estas historias ayudan al equipo de desarrollo de Chrome a priorizar. Estas historias muestran a los creadores de otros navegadores la importancia de admitir nuevas funciones. Si lo desea, envíe un tweet a @ChromiumDev y cuéntenos dónde y cómo usa la nueva API.

¡Queridos lectores! ¿Lo has intentado performance.measureMemory()?


All Articles