Cómo y por qué creamos estadísticas de rendimiento

En Chrome 102, verás un nuevo panel experimental, Estadísticas de rendimiento, en tus Herramientas para desarrolladores. En esta publicación, no solo analizaremos los motivos por los que trabajamos en un panel nuevo, sino también los desafíos técnicos que nos enfrentamos y las decisiones que tomamos en el camino.

ALT_TEXT_HERE

¿Por qué crear otro panel?

(Si aún no lo has visto, publicamos un video sobre por qué crear el panel Estadísticas de rendimiento y cómo puedes obtener estadísticas prácticas sobre el rendimiento de tu sitio web con él).

El Panel de rendimiento existente es un excelente recurso si quieres ver todos los datos de tu sitio web en un solo lugar, pero consideramos que puede ser un poco abrumador. Si no eres un experto en rendimiento, es difícil saber exactamente qué buscar y qué partes de la grabación son relevantes.

Ingresa al Panel de estadísticas, donde aún puedes ver una línea de tiempo del seguimiento e inspeccionar los datos, y obtener una lista práctica de lo que Herramientas para desarrolladores considera que son las "estadísticas" principales a las que vale la pena indagar. Las estadísticas identificarán problemas como las solicitudes que bloquean la renderización, los cambios de diseño y las tareas largas, por nombrar solo algunos que pueden afectar negativamente el rendimiento de carga de la página de tu sitio web y, en particular, las puntuaciones de las Métricas web esenciales (CWV) de tu sitio. Además de marcar los problemas, las estadísticas de rendimiento te brindarán sugerencias prácticas para mejorar tus puntuaciones de CWV y vínculos a más recursos y documentación.

Vínculo de comentarios en el panel

Este panel es experimental y queremos conocer tus comentarios. Infórmanos si encuentras algún error o solicitas funciones que creas que te ayudarán a trabajar en el rendimiento de tu sitio.

Cómo creamos las Estadísticas de rendimiento

Al igual que con el resto de Herramientas para desarrolladores, compilamos Estadísticas de rendimiento en TypeScript y usamos componentes web, respaldados por lit-html, para compilar la interfaz de usuario. Las estadísticas de rendimiento difieren en que la interfaz principal de la IU es un elemento HTML canvas, y el cronograma se dibuja en este lienzo. Gran parte de la complejidad proviene de administrar este lienzo: no solo dibujar los detalles correctos en el lugar correcto, sino también administrar los eventos del mouse (por ejemplo, ¿dónde hizo clic el usuario en el lienzo? ¿Hizo clic en un evento que dibujamos?) y se aseguró de volver a representar el lienzo con eficacia.

Varias pistas en un solo lienzo

Para un sitio web determinado, hay varios "segmentos" que queremos renderizar, cada uno de los cuales representa una categoría de datos diferente. Por ejemplo, el panel Estadísticas mostrará tres segmentos de forma predeterminada:

A medida que vayamos mostrando elementos en el panel, esperamos que se agreguen más pistas.

Nuestra idea inicial fue que cada una de estas pistas renderizara su propio <canvas>, de modo que la vista principal se convirtiera en varios elementos de lienzo apilados verticalmente. Esto simplificaría la renderización a nivel de pista, ya que cada pista podría renderizarse de forma aislada y no habría el peligro de que la renderización de la pista fuera de sus límites, pero, lamentablemente, este enfoque tiene dos problemas importantes:

Los elementos canvas son costosos de (volver a) renderizar. Tener varios lienzos es más costoso que un lienzo, incluso si ese lienzo es más grande. El procesamiento de cualquier superposición que abarque varios segmentos (por ejemplo, líneas verticales para marcar eventos, como el tiempo de FCP) se vuelve complejo: tenemos que renderizarlos en varios lienzos y asegurarnos de que todos se rendericen juntos y se alineen correctamente.

El uso de un canvas para toda la IU significaba que necesitábamos averiguar cómo garantizar que cada pista se renderizara en las coordenadas correctas y no se desbordara en otra pista. Por ejemplo, si una pista en particular tiene 100 px de alto, no podemos permitir que procese algo de 120 px de alto y que se aplique a la pista que está debajo de ella. Para resolver este problema, podemos usar clip. Antes de renderizar cada seguimiento, dibujamos un rectángulo que representa la ventana visible del recorrido. Esto garantiza que el lienzo recorte cualquier ruta dibujada fuera de estos límites.

canvasContext.beginPath();
canvasContext.rect(
    trackVisibleWindow.x, trackVisibleWindow.y, trackVisibleWindow.width, trackVisibleWindow.height);
canvasContext.clip();

Tampoco queríamos que cada pista contuviera su posición vertical: cada pista se renderizaría como si se renderizara en (0, 0), y tenemos un componente de nivel superior (al que llamamos TrackManager) para administrar la posición general de la pista. Para ello, usa translate, que traduce el lienzo en una posición determinada (x, y). Por ejemplo:

canvasContext.translate(0, 10); // Translate by 10px in the y direction
canvasContext.rect(0, 0, 10, 10); // draw a rectangle at (0, 0) that’s 10px high and wide

A pesar de que el código rect establezca 0, 0 como la posición, la traslación general aplicada hará que el rectángulo se renderice en 0, 10. De esta manera, podemos trabajar en cada pista como si estuviéramos renderizando en (0, 0) y hacer que nuestro administrador de pistas traduzca a medida que renderiza cada pista para garantizar que se renderice correctamente debajo de la anterior.

Lienzos fuera de pantalla de pistas y contenido destacado

La renderización de lienzos es relativamente costosa, y queremos asegurarnos de que el panel de estadísticas se mantenga fluido y responsivo mientras trabajas con él. A veces, no es posible evitar tener que volver a renderizar todo el lienzo. Por ejemplo, si cambias el nivel de zoom, tendremos que volver a empezar y renderizar todo. La repetición de renderizaciones de lienzos es particularmente costosa porque no se puede volver a renderizar una pequeña parte de ella, sino que debes limpiar todo el lienzo y volver a dibujar. Esto se diferencia de la nueva renderización del DOM, en la que las herramientas pueden calcular el trabajo mínimo requerido y no quitar todo y comenzar de nuevo.

Un área en la que detectamos problemas visuales fue destacar. Cuando colocas el cursor sobre las métricas del panel, las destacamos en la línea de tiempo y, del mismo modo, si pasas el cursor sobre una Estadística de un evento determinado, dibujamos un borde azul alrededor de ese evento.

Esta función se implementó primero detectando cómo un mouse se desplaza sobre un elemento que activa un destacado y, luego, dibuja ese resaltado directamente en el lienzo principal. Nuestro problema surge cuando tenemos que quitar el destacado: la única opción es volver a dibujar todo. Es imposible volver a dibujar el área donde estaba el destacado (no sin grandes cambios arquitectónicos), pero volver a dibujar todo el lienzo solo porque queríamos quitar un borde azul alrededor de un elemento sentía que era excesivo. También se retrasaba visualmente si movías el mouse sobre diferentes elementos para activar varias opciones destacadas en una sucesión rápida.

Para solucionar este problema, dividimos nuestra IU en dos lienzos fuera de la pantalla: el lienzo “principal”, donde se renderizan las pistas, y el lienzo “de contenido destacado”, donde se dibujan los elementos destacados. Luego, renderizamos esos lienzos en el único que es visible en la pantalla. Podemos usar el método drawImage en un contexto de lienzo, que puede tomar otro lienzo como fuente.

Esto significa que quitar el resaltado no hará que se vuelva a dibujar el lienzo principal: en su lugar, podemos borrar el lienzo de la pantalla y, luego, copiar el lienzo principal en el lienzo visible. Copiar un lienzo es económico. El dibujo es costoso, por lo que si mueves las zonas brillantes a otro lienzo, evitamos el costo de activar o desactivar las zonas brillantes.

Análisis de seguimiento probado de manera exhaustiva

Uno de los beneficios de crear una función nueva desde cero es que puedes reflexionar sobre las decisiones técnicas que tomaste anteriormente y realizar mejoras. Uno de los aspectos que queríamos mejorar era dividir explícitamente nuestro código en dos partes, casi completamente distintas:

Analizar el archivo de registro y extraer los datos requeridos Renderiza un conjunto de pistas.

Mantener el análisis (parte 1) separado del trabajo de la IU (parte 2) nos permitió crear un sistema de análisis sólido; cada seguimiento se ejecuta a través de una serie de controladores responsables de diferentes preocupaciones: un LayoutShiftHandler calcula toda la información que necesitamos para los cambios de diseño y un NetworkRequestsHandler se encarga de manera exclusiva de extraer solicitudes de red. También es beneficioso tener este paso de análisis explícito en el que tenemos diferentes controladores responsables de distintas partes del seguimiento: el análisis de seguimiento puede ser muy complicado y ayuda a poder enfocarse en un problema a la vez.

También pudimos probar de manera exhaustiva nuestro análisis de seguimiento. Para ello, tomamos grabaciones en Herramientas para desarrolladores, las guardamos y las cargamos como parte de nuestro paquete de pruebas. Esto es genial porque podemos realizar pruebas con seguimientos reales y no acumular grandes cantidades de datos de seguimiento falsos que podrían quedar obsoletos.

Prueba de capturas de pantalla de la IU de Canvas

Manteniéndonos en el tema de las pruebas, por lo general, probamos nuestros componentes de frontend mediante su renderización en el navegador y asegurándonos de que se comporten como se espera. Podemos enviar eventos de clic para activar las actualizaciones y afirmar que el DOM que generan los componentes es correcto. Este enfoque funciona bien para nosotros, pero falla cuando se considera la renderización en un lienzo, ya que no hay forma de inspeccionar un lienzo y determinar lo que se dibuja allí. Por lo tanto, nuestro enfoque habitual de renderización y consulta no es apropiado.

Para poder tener algo de cobertura, recurrimos a la prueba de capturas de pantalla. Cada prueba activa un lienzo, renderiza el segmento que queremos probar y, luego, toma una captura de pantalla del elemento de lienzo. Luego, esta captura de pantalla se almacena en nuestra base de código y, en las próximas pruebas, se comparará la captura de pantalla almacenada con la que se genere. Si las capturas de pantalla son diferentes, la prueba fallará. También proporcionamos una marca para ejecutar la prueba y forzar la actualización de una captura de pantalla cuando cambiamos intencionalmente la renderización y necesitamos actualizar la prueba.

Las pruebas de capturas de pantalla no son perfectas y son un poco directas. Solo puedes probar que el componente completo se dibuje como se espera, en lugar de aserciones más específicas, y al principio tuvimos la culpa de usarlas en exceso para garantizar que cada componente (HTML o lienzo) se procesara correctamente. Esto ralentizó drásticamente nuestro paquete de pruebas y generó problemas por los que pequeños ajustes de la IU casi irrelevantes (como cambios sutiles de color o agregar algún margen entre los elementos) provocaban errores en varias capturas de pantalla y se debían actualizar. Redujimos el uso de las capturas de pantalla y las usamos exclusivamente para componentes basados en lienzos. Este equilibrio nos ha funcionado hasta ahora.

Conclusión

La creación del nuevo panel de Estadísticas de rendimiento ha sido una experiencia muy agradable y educativa para el equipo. Aprendimos mucho sobre los archivos de registro, el trabajo con el lienzo y mucho más. Esperamos que disfrutes usar el nuevo panel. Estamos ansiosos por conocer tus comentarios.

Para obtener más información sobre el panel Estadísticas de rendimiento, consulta el artículo Estadísticas de rendimiento: Obtén estadísticas prácticas sobre el rendimiento de tu sitio web.

Descarga los canales de vista previa

Considera usar Canary, Dev o Beta de Chrome como tu navegador de desarrollo predeterminado. Estos canales de vista previa te brindan acceso a las funciones más recientes de Herramientas para desarrolladores, prueba APIs de plataformas web de vanguardia y encuentra problemas en tu sitio antes que tus usuarios.

Cómo comunicarse con el equipo de Herramientas para desarrolladores de Chrome

Usa las siguientes opciones para analizar las nuevas funciones y los cambios en la publicación, o cualquier otra cosa relacionada con Herramientas para desarrolladores.

  • Envíanos tus sugerencias o comentarios a través de crbug.com.
  • Informa un problema en Herramientas para desarrolladores mediante Más opciones   Más   > Ayuda > Informar problemas con Herramientas para desarrolladores en Herramientas para desarrolladores.
  • Envía un tweet a @ChromeDevTools.
  • Deja comentarios en los videos de YouTube de las Novedades de las Herramientas para desarrolladores o en las sugerencias de Herramientas para desarrolladores (videos de YouTube).