En Chrome 102, verás un nuevo panel experimental, Estadísticas de rendimiento, en DevTools. En esta publicación, hablaremos no solo de por qué trabajamos en un nuevo panel, sino también de los desafíos técnicos que enfrentamos y las decisiones que tomamos en el camino.
¿Por qué crear otro panel?
Si aún no lo viste, publicamos un video en el que explicamos los motivos para crear el panel de 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 deseas ver todos los datos de tu sitio web en un solo lugar, pero consideramos que podría 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, en el que puedes ver un cronograma de tu seguimiento y también inspeccionar los datos, además de obtener una lista práctica de lo que DevTools considera las principales "Estadísticas" que vale la pena analizar. Las estadísticas identificarán problemas, como solicitudes de bloqueo de renderización, cambios de diseño y tareas largas, entre otros, que pueden afectar negativamente el rendimiento de carga de páginas de tu sitio web y, específicamente, las puntuaciones de Métricas web esenciales (CWV) de tu sitio. Además de marcar los problemas, las estadísticas de rendimiento te proporcionarán sugerencias prácticas para mejorar tus puntuaciones de CWV y vínculos a más recursos y documentación.
Este panel es experimental y queremos conocer tus comentarios. Avísanos si encuentras algún error o tienes solicitudes de funciones que crees que te ayudarán a mejorar el rendimiento de tu sitio.
Cómo creamos las Estadísticas de rendimiento
Al igual que con el resto de las Herramientas para desarrolladores, creamos Estadísticas de rendimiento en TypeScript y usamos componentes web, respaldados por lit-html, para compilar la interfaz de usuario. La diferencia entre las Estadísticas de rendimiento es 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 la administración de este lienzo: no solo dibujar los detalles correctos en el lugar correcto, sino también administrar los eventos del mouse (por ejemplo, ¿en qué parte del lienzo hizo clic el usuario? ¿Hicieron clic en un evento que dibujamos?) y se aseguraron de volver a representar el lienzo de manera eficaz.
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 diferente de datos. Por ejemplo, el panel de estadísticas mostrará tres segmentos de forma predeterminada:
A medida que vayamos incorporando funciones en el panel, esperamos que se agreguen más pistas.
Nuestra idea inicial era que cada uno de estos segmentos 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 la pista, ya que cada una podría renderizarse de forma aislada y no habría peligro de que se renderice fuera de sus límites. Lamentablemente, este enfoque tiene dos problemas principales:
Los elementos canvas
son costosos de renderizar (o volver a renderizar). Tener varios lienzos es más costoso que tener uno, incluso si ese lienzo es más grande.
La renderización de superposiciones que abarcan varias pistas (por ejemplo, líneas verticales para marcar eventos, como el tiempo de FCP) se vuelve compleja: debemos renderizar en varios lienzos y asegurarnos de que todos se rendericen juntos y se alineen correctamente.
Usar un canvas
para toda la IU significaba que debíamos descubrir cómo garantizar que cada segmento se renderice en las coordenadas correctas y no se desborde en otro. Por ejemplo, si una pista específica es de 100 px de alto, no podemos permitir que renderice algo que sea de 120 px de alto y que se inserte en la pista que está debajo de ella. Para solucionar este problema, podemos usar clip
. Antes de renderizar cada segmento, dibujamos un rectángulo que representa la ventana de segmento visible. Esto garantiza que cualquier ruta dibujada fuera de estos límites se recortará por el lienzo.
canvasContext.beginPath();
canvasContext.rect(
trackVisibleWindow.x, trackVisibleWindow.y, trackVisibleWindow.width, trackVisibleWindow.height);
canvasContext.clip();
Tampoco queríamos que cada pista tuviera que conocer su posición verticalmente: cada pista debería renderizarse como si se estuviera renderizando en (0, 0), y tenemos un componente de nivel superior (al que llamamos TrackManager
) para administrar la posición general de la pista. Esto se puede hacer con translate
, que traduce el lienzo según 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
establece 0, 0
como la posición, la traducción general aplicada hará que el rectángulo se renderice en 0, 10
. Esto nos permite trabajar en cada pista como si la renderizáramos en (0, 0) y hacer que nuestro administrador de pistas realice la traducción a medida que renderiza cada pista para garantizar que se renderice correctamente debajo de la anterior.
Lienzos fuera de pantalla para pistas y contenido destacado
La renderización de Canvas es relativamente costosa, y queremos asegurarnos de que el panel de estadísticas siga siendo fluido y responsivo mientras trabajas con él. En ocasiones, es posible que no tengas que volver a renderizar todo el lienzo. Por ejemplo, si cambias el nivel de zoom, tendremos que volver a renderizar todo. La nueva renderización del lienzo es particularmente costosa porque no puedes volver a renderizar solo una pequeña parte. Debes borrar todo el lienzo y volver a dibujarlo. Esto es diferente 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 tuvimos problemas visuales fue el resaltado. Cuando colocas el cursor sobre las métricas del panel, las destacamos en el cronograma. Del mismo modo, si colocas el cursor sobre una estadística de un evento determinado, dibujamos un borde azul alrededor de ese evento.
Esta función se implementó por primera vez detectando el movimiento del mouse sobre un elemento que activa un elemento destacado y, luego, dibujando ese elemento directamente en el lienzo principal. Nuestro problema se presenta cuando tenemos que quitar lo destacado: la única opción es volver a dibujar todo. Es imposible volver a dibujar el área donde estaba el punto destacado (no sin grandes cambios arquitectónicos), pero volver a dibujar el lienzo completo solo porque queremos quitar un borde azul alrededor de un elemento. También se retrasó visualmente si moviste el mouse rápidamente sobre diferentes elementos para activar varios elementos destacados en una sucesión rápida.
Para solucionar este problema, dividimos nuestra IU en dos lienzos fuera de la pantalla: el lienzo “principal”, en el que se renderizan los segmentos, y el lienzo “de elementos destacados”, en el que se dibujan los elementos destacados. Luego, copiamos esos lienzos en el único lienzo que el usuario puede ver 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 un elemento destacado no hace que se vuelva a dibujar el lienzo principal: en su lugar, podemos borrar el lienzo en pantalla y, luego, copiar el lienzo principal en el lienzo visible. El acto de copiar un lienzo es económico, el dibujo es lo costoso. Por lo tanto, si movemos los elementos destacados a un lienzo separado, evitamos ese costo cuando los activamos y desactivamos.
Análisis de seguimientos probados 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. Una de las cosas que queríamos mejorar era dividir nuestro código de forma explícita en dos partes casi completamente distintas:
Analiza el archivo de seguimiento y extrae los datos necesarios. Renderiza un conjunto de pistas.
Mantener el análisis (parte 1) separado del trabajo de la IU (parte 2) nos permitió compilar un sistema de análisis sólido. Cada seguimiento se ejecuta a través de una serie de controladores que son responsables de diferentes inquietudes: un LayoutShiftHandler
calcula toda la información que necesitamos para los cambios de diseño y un NetworkRequestsHandler
se encarga exclusivamente de extraer las solicitudes de red. Tener este paso de análisis explícito en el que tenemos diferentes controladores responsables de diferentes partes del seguimiento también fue beneficioso: el análisis de seguimiento puede complicarse mucho y ayuda a poder enfocarse en un problema a la vez.
También pudimos probar de forma integral nuestro análisis de seguimientos. Para ello, tomamos grabaciones en DevTools, las guardamos y, luego, las cargamos como parte de nuestro paquete de pruebas. Esto es excelente porque podemos realizar pruebas con registros reales y no acumular grandes cantidades de datos de registro falsos que podrían volverse obsoletos.
Prueba de capturas de pantalla para la IU de Canvas
Siguiendo con el tema de las pruebas, por lo general, probamos nuestros componentes de frontend renderizando los componentes en el navegador y asegurándonos de que se comporten como se espera. Podemos enviar eventos de clic para activar 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. No hay forma de inspeccionar un lienzo y determinar qué se dibuja allí. Por lo tanto, nuestro enfoque habitual de renderización y, luego, consulta no es adecuado.
Para poder tener cierta cobertura de pruebas, recurrimos a las pruebas de capturas de pantalla. Cada prueba inicia un lienzo, renderiza la pista que queremos probar y, luego, toma una captura de pantalla del elemento del lienzo. Luego, esta captura de pantalla se almacena en nuestra base de código, y las ejecuciones de prueba futuras compararán la captura de pantalla almacenada con la que generan. Si las capturas de pantalla son diferentes, la prueba fallará. También proporcionamos una marca para ejecutar la prueba y forzar una actualización de la captura de pantalla cuando cambiamos la renderización de forma intencional y necesitamos que se actualice la prueba.
Las pruebas de capturas de pantalla no son perfectas y son un poco toscas. Solo puedes probar que todo el componente se renderice como se espera, en lugar de aserciones más específicas, y, en un principio, abusamos de ellas para asegurarnos de que cada componente (HTML o lienzo) se renderizara correctamente. Esto ralentizó nuestro conjunto de pruebas de forma drástica y generó problemas en los que pequeños ajustes irrelevantes de la IU (como cambios de color sutiles o la adición de un margen entre los elementos) provocaron que varias capturas de pantalla fallaran y necesitaran actualizarse. Ahora reducimos el uso de capturas de pantalla y las usamos solo para componentes basados en lienzo, y este equilibrio nos ha funcionado bien hasta ahora.
Conclusión
Crear el nuevo panel Estadísticas de rendimiento fue una experiencia educativa y muy agradable para el equipo. Aprendimos mucho sobre los archivos de registro, cómo trabajar con el lienzo y mucho más. Esperamos que disfrutes usando el nuevo panel y estamos ansiosos por conocer tus comentarios.
Para obtener más información sobre el panel Estadísticas de rendimiento, consulta 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 Chrome Canary, Dev o Beta como tu navegador de desarrollo predeterminado. Estos canales de versión preliminar te brindan acceso a las funciones más recientes de DevTools, te permiten probar las APIs de plataformas web de vanguardia y te ayudan a encontrar problemas en tu sitio antes que tus usuarios.
Comunícate con el equipo de Herramientas para desarrolladores de Chrome
Usa las siguientes opciones para hablar sobre las nuevas funciones, actualizaciones o cualquier otro aspecto relacionado con Herramientas para desarrolladores.
- Envíanos tus comentarios y solicitudes de funciones a crbug.com.
- Informa un problema de DevTools con Más opciones > Ayuda > Informar un problema de DevTools en DevTools.
- Twittea a @ChromeDevTools.
- Deja comentarios en los videos de YouTube sobre las novedades de DevTools o en los videos de YouTube sobre sugerencias de DevTools.