Usa el panel Rendimiento de las Herramientas para desarrolladores de Chrome para generar perfiles de apps de Angular

Andrés Olivares
Andrés Olivares
Pawel Kozlowski
Pawel Kozlowski

Los frameworks web, como Angular, React, Vue y Svelte, facilitan la escritura y el mantenimiento de aplicaciones web complejas a gran escala.

Sin embargo, estos frameworks introducen una capa de abstracción sobre el modelo de aplicación del navegador. De hecho, el código que escriben los desarrolladores que usan estas abstracciones suele transpilarse en código ilegible, minimizado y agrupado. Como consecuencia, aprovechar al máximo el poder de DevTools para depurar y generar perfiles de estas apps puede ser un desafío para los desarrolladores.

Por ejemplo, cuando se genera un perfil de una aplicación de Angular con el panel Rendimiento en las Herramientas para desarrolladores, verás lo siguiente:

La vista de seguimiento del panel Rendimiento muestra la línea de tiempo de una carga de página obtenida de una app de Angular. Se enfoca en el carril del subproceso principal expandido, que muestra un gráfico de llamas de las llamadas de JavaScript con nombres minimizados.
Vista de registro del panel de rendimiento.

Con la información presentada de esta manera, puede ser difícil determinar qué cuellos de botella de rendimiento existen en tu base de código. Después de todo, le falta el contexto de las construcciones del framework y una buena parte de la información que se muestra está en términos de código minimizado. También es difícil distinguir entre la actividad relacionada directamente con el código que escribiste, los elementos internos del framework y otro código de terceros que podría ejecutarse en la misma página.

Una motivación común para los autores de frameworks y abstracciones es implementar sus propias extensiones de DevTools que presenten los datos de generación de perfiles en términos de los conceptos del framework. Estas herramientas son muy útiles cuando se depuran y se generan perfiles de aplicaciones compiladas con un framework específico. Sin embargo, a menudo necesitarás correlacionar los datos del framework en el propio generador de perfiles del framework con la información del tiempo de ejecución del navegador en el panel Rendimiento de las Herramientas para desarrolladores. Tener estas dos fuentes de datos presentadas por separado en herramientas independientes dificulta la detección y la corrección de los embotellamientos, especialmente a medida que la aplicación se vuelve más compleja. Este es un ejemplo de una visualización de perfil en el generador de perfiles de Angular DevTools:

La pestaña Profiler en Angular DevTools, que muestra un gráfico tipo llama del tiempo de ejecución de una app de Angular. Los elementos que componen el gráfico tipo llama tienen etiquetas que son legibles y recuerdan los nombres de los componentes de Angular.
Generador de perfiles de Herramientas para desarrolladores de Angular.

En un mundo ideal, los desarrolladores tendrían una vista en la que las dos fuentes de datos se mostrarían juntas en el mismo contexto asignado a la misma línea de tiempo.

Por este motivo, colaboramos con el equipo de Angular para incorporar datos de tiempo de ejecución de Angular directamente en el panel Rendimiento con la API de extensibilidad del panel Rendimiento. En esta publicación, analizaremos qué puede hacer la API y cómo se usó en el framework de Angular para lograrlo. La implementación puede servir como ejemplo para otros frameworks y abstracciones que buscan mejorar su experiencia del desarrollador instrumentando sus propias herramientas y ayudando a los desarrolladores que usan las Herramientas para desarrolladores de Chrome.

¿Qué es la API de extensibilidad del panel Rendimiento?

La API te permite agregar tus propias entradas de tiempo al registro del panel Rendimiento, dentro de la misma línea de tiempo que el resto de los datos del navegador. Existen dos mecanismos que te permiten hacerlo:

  • La API de User Timing
  • La API de console.timeStamp

La API de User Timing

Puedes usar performance.mark y performance.measure para agregar las entradas de la siguiente manera:


// Mark used to represent the start of some activity you want to measure.
// In this case, the rendering of a component.
const renderStart = performance.now();

// ... later in your code

performance.measure("Component rendering", {
  start: renderStart,
  detail: {
    devtools: {
      dataType: "track-entry",
      track: "Components",
      color: "secondary",
      properties: [
        ["Render reason", "Props changed"],
        ["Priority", "low"]
      ],
    }
  }
});

Esto hará que se agregue la pista Components a tu línea de tiempo con la medición:

Es la vista de seguimiento del panel Rendimiento. Se enfoca en el segmento personalizado expandido llamado "Componentes", que contiene una medición llamada "Renderización de componentes".
Pista personalizada en el panel de rendimiento.

Esta API te permite agregar las entradas al búfer de la línea de tiempo de rendimiento y mostrarlas en la IU del panel Rendimiento de DevTools.

Obtén más información sobre esta API y el objeto devtools en la documentación.

La API de console.timeStamp

Esta API es una alternativa liviana a la API de User Timing. Con el mismo ejemplo anterior, podrías tener lo siguiente:


// Mark used to represent the start of some activity you want to measure.
// In this case, the rendering of a component.
const renderStart = performance.now();

// ... later in your code

console.timeStamp(
"Component rendering",
/* start time */ renderStart,
/* end time (current time) */ undefined,
/* track name */ "Components",
 /* track group name */ undefined,
 /* color */ "secondary"
);

Esta API proporciona un método de alto rendimiento para instrumentar aplicaciones: a diferencia de la alternativa de la API de User Timing, no crea datos almacenados en búfer. Esta API solo agrega datos al panel **Rendimiento** en Herramientas para desarrolladores, lo que significa que, cuando Herramientas para desarrolladores no está grabando un registro, las llamadas a la API no realizan ninguna operación (no hacen nada), lo que la hace significativamente más rápida y adecuada para las rutas de acceso activas sensibles al rendimiento. La elección de usar argumentos posicionales en lugar de un objeto que contenga todos los parámetros de personalización también tiene el propósito de mantener la API lo más ligera posible.

Obtén más información para usar console.timeStamp y extender el panel Rendimiento, así como los parámetros que puedes pasar en la documentación.

Cómo Angular integró la API de extensibilidad de DevTools

Analizaremos cómo el equipo de Angular usó la API de extensibilidad para integrarse en las Herramientas para desarrolladores de Chrome.

Evita la sobrecarga con console.timestamp

La instrumentación de Angular con la API de extensibilidad del panel Performance está disponible a partir de la versión 20. El nivel de detalle deseado para los datos de rendimiento en DevTools requiere una API rápida, por lo que la solicitud de extracción (60217) que agregó la instrumentación optó por usar la API de console.timeStamp. Esto evita que el rendimiento del tiempo de ejecución de la aplicación se vea afectado por la posible sobrecarga de la API de generación de perfiles.

Datos instrumentados

Para proporcionar una buena imagen de qué código de Angular se está ejecutando y por qué se está ejecutando, se instrumentan varias partes de las canalizaciones de inicio y renderización, incluidas las siguientes:

  • Arranque de la aplicación y los componentes
  • Creación y actualización de componentes
  • Ejecución de objetos de escucha de eventos y hooks de ciclo de vida
  • Muchas otras (por ejemplo, la creación de componentes dinámicos y la renderización de bloques diferida).

Programación de color

El código de color se usa para indicarle al desarrollador la categoría en la que se incluye una determinada entrada de medición. Por ejemplo, los colores que se usan para las entradas que marcan la ejecución del código de TypeScript creado por el desarrollador son distintos de los colores que se usan para el código producido por el compilador de Angular.

En la siguiente captura de pantalla, puedes ver cómo esto genera puntos de entrada (como la detección de cambios y el procesamiento de componentes) en azul, código generado en púrpura y código de TypeScript (como los hooks y los controladores de eventos) renderizado en verde.

Es la vista de seguimiento del panel Rendimiento. Se enfoca en el segmento personalizado expandido llamado "Angular", que contiene un gráfico de llamas con mediciones de diferentes colores que representan la actividad del tiempo de ejecución de una app de Angular de una manera fácil de usar para los desarrolladores.
Códigos de color en el panel Rendimiento.

Ten en cuenta que el argumento de color que se pasa a la API no es un valor de color CSS, sino un token semántico que se asigna a un color que coincide con la IU de Herramientas para desarrolladores. Los valores posibles son primary, secondary y tertiary, con sus respectivas variantes -dark y -light, así como un color error.

Pistas

En el momento de escribir este artículo, todos los datos de tiempo de ejecución de Angular se agregan al mismo segmento (etiquetado como "🅰️ Angular"). Sin embargo, es posible agregar varias pistas al registro e incluso agruparlas. Por ejemplo, dadas las siguientes llamadas a la API de console.timeStamp:

console.timeStamp("Component 1", componentStart1, componentEnd1, "Components", "Client", "primary");
console.timeStamp("Component 2", componentStart2, componentEnd2, "Components", "Client", "primary");
console.timeStamp("Hook 1", hookStart, hookEnd, "Hooks", "Client", "primary");
console.timeStamp("Fetch data base", fetchStart, fetchEnd, "Server", "primary");

Verías los datos organizados en segmentos de la siguiente manera:

Es la vista de seguimiento del panel Rendimiento. Se enfoca en los múltiples segmentos personalizados expandidos, cada uno con diferentes mediciones internas.
Varios segmentos personalizados en el panel Rendimiento.

Usar pistas separadas puede ser útil, por ejemplo, cuando tienes actividad asíncrona, varios trabajos que se ejecutan en paralelo o simplemente grupos de actividad lo suficientemente distintos como para que valga la pena separarlos en diferentes áreas de la IU.

Por qué esto es importante para los desarrolladores de Angular

El objetivo de esta integración directa es proporcionar una experiencia de análisis del rendimiento más intuitiva y completa. Al mostrar los datos de rendimiento internos de Angular directamente en el panel **Rendimiento**, los desarrolladores obtendrán lo siguiente:

  • Visibilidad mejorada: Los eventos de rendimiento específicos de Angular, como la renderización de componentes, los ciclos de detección de cambios y mucho más, se hacen visibles en el cronograma más amplio del navegador.
  • Comprensión mejorada: Con información enriquecida en contexto sobre los procesos internos de Angular, lo que te ayuda a identificar los cuellos de botella del rendimiento de manera más eficaz.

Cómo habilitar la integración

El uso de la API de extensibilidad está disponible oficialmente en las compilaciones de desarrollo a partir de la versión 20 de Angular. Para habilitarlo, debes ejecutar la utilidad global `ng.enableProfiling()` en tu app o en la consola de Herramientas para desarrolladores. Obtén más información sobre la integración en la [documentación de Angular](https://angular.dev/best-practices/profiling-with-chrome-devtools).

Otras consideraciones

Algunas consideraciones importantes que se deben tener en cuenta.

Mapas de orígenes y código reducido:

Los mapas de origen son una herramienta ampliamente adoptada que tiene como objetivo cerrar la brecha entre el código agrupado o reducido y su contraparte creada, por lo que…

¿No se supone que los mapas de origen resuelven el problema del código reducido en las apps agrupadas?

Si bien los mapas de origen son útiles, no eliminan por completo los desafíos cuando se perfilan apps web complejas minimizadas. Los mapas de orígenes permiten que DevTools vuelva a asignar el código reducido a tu código fuente original, lo que facilita la depuración. Sin embargo, depender únicamente de los mapas de origen para el análisis del rendimiento puede presentar algunas limitaciones. Por ejemplo, elegir la forma en que los elementos internos del framework y el código creado se separan visualmente es complicado solo con los mapas de fuentes. Por otro lado, la API de extensibilidad proporciona la flexibilidad necesaria para lograr esta distinción y presentarla de la manera que el desarrollador considere más conveniente.

Extensiones de Herramientas para desarrolladores de Chrome:

Las extensiones de Chrome que usan la API de DevTools son una herramienta muy utilizada para extender las herramientas para desarrolladores.

¿Los generadores de perfiles dedicados (por ejemplo, las extensiones de las Herramientas para desarrolladores de Chrome) son innecesarios o están desaconsejados ahora que esta API está disponible?

No, esta API no está diseñada para reemplazar ni desalentar el desarrollo de analizadores dedicados, como las extensiones de Herramientas para desarrolladores de Chrome. Aun así, pueden ofrecer funciones, visualizaciones y flujos de trabajo especializados y adaptados a necesidades específicas. El objetivo de la API de extensibilidad del panel Rendimiento es crear una integración perfecta de los datos personalizados con las visualizaciones del navegador en el panel Rendimiento.

El camino a seguir

Es el prospecto de la API de extensibilidad.

Trabajar con más frameworks y abstracciones

Nos entusiasman otros frameworks y abstracciones que adoptan la API para mejorar la experiencia de generación de perfiles de sus desarrolladores. Por ejemplo, React implementó una adopción experimental de la API para su framework. Esta instrumentación muestra la renderización de componentes del cliente y del servidor, así como los datos de las APIs de programación de React. Obtén más información sobre esta función y cómo habilitarla en la página de React.

Compilaciones de producción

Uno de los objetivos de esta API es trabajar con frameworks y proveedores de abstracción en general para adoptar y habilitar la instrumentación en compilaciones de producción. Esto podría tener un gran impacto en el rendimiento de las apps desarrolladas con estas abstracciones, ya que los desarrolladores podrían crear perfiles de la aplicación tal como la experimentan sus usuarios. Creemos que la API de console.timeStamp permite lograr esto, dada su velocidad y su baja sobrecarga. Sin embargo, por el momento, los frameworks siguen experimentando con la API y analizando qué tipos de instrumentaciones son más escalables y útiles para los desarrolladores.