Usar o painel "Performance" do Chrome DevTools para criar perfis de apps Angular

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

Frameworks da Web como Angular, React, Vue e Svelte facilitam a criação e a manutenção de aplicativos da Web complexos em grande escala.

No entanto, esses frameworks introduzem uma camada de abstração sobre o modelo de aplicativo do navegador. Na verdade, o código escrito por desenvolvedores usando essas abstrações geralmente acaba sendo transpilado em um código ilegível, minimizado e agrupado. Como consequência, aproveitar ao máximo o poder das DevTools para depurar e criar perfis desses apps pode ser um desafio para os desenvolvedores.

Por exemplo, ao criar um perfil de um aplicativo Angular com o painel Performance no DevTools, você verá o seguinte:

A visualização de rastreamento do painel "Performance" mostrando a linha do tempo de um carregamento de página obtido de um app Angular. Ela se concentra na faixa da linha principal expandida, que mostra um gráfico de chamas de chamadas JavaScript com nomes minimizados.
Visualização de rastreamento do painel de performance.

Com as informações apresentadas dessa forma, fica difícil descobrir quais gargalos de performance existem na sua base de código. Afinal, ele não tem o contexto das construções do framework, e boa parte das informações mostradas está em termos de código minimizado. Também é difícil distinguir entre a atividade diretamente relacionada ao código que você escreveu, os internos do framework e outros códigos de terceiros que podem estar sendo executados na mesma página.

Uma motivação comum para autores de frameworks e abstrações é implementar as próprias extensões do DevTools, que apresentam dados de criação de perfil em termos de conceitos do framework. Essas ferramentas são muito úteis ao depurar e criar perfis de aplicativos criados com uma estrutura específica. No entanto, na maioria das vezes, você vai precisar correlacionar os dados do framework no próprio criador de perfil dele com as informações de tempo de execução do navegador no painel Performance do DevTools. Ter essas duas fontes de dados apresentadas separadamente em ferramentas independentes dificulta a identificação e a correção de gargalos, especialmente à medida que o aplicativo se torna mais complexo. Confira um exemplo de visualização de perfil no Profiler do Angular DevTools:

A guia "Profiler" nas DevTools do Angular, mostrando um gráfico de chamas do tempo de execução de um app Angular. Os itens que compõem o gráfico de chamas têm rótulos legíveis e que lembram nomes de componentes do Angular.
Profiler do Angular DevTools.

O ideal seria que os desenvolvedores tivessem uma visualização em que as duas fontes de dados fossem mostradas juntas no mesmo contexto mapeado para a mesma linha do tempo.

Por isso, colaboramos com a equipe do Angular para trazer dados de tempo de execução do Angular diretamente para o painel Performance usando a API de extensibilidade do painel Performance. Nesta postagem, vamos analisar o que a API pode fazer e como ela foi usada no framework Angular para alcançar esse objetivo. A implementação pode servir como exemplo para outros frameworks e abstrações que buscam melhorar a experiência do desenvolvedor instrumentando as próprias ferramentas e ajudando os desenvolvedores a usar o Chrome DevTools.

O que é a API de extensibilidade do painel "Desempenho"?

A API permite adicionar suas próprias entradas de tempo ao rastreamento do painel Performance, na mesma linha do tempo que o restante dos dados do navegador. Há dois mecanismos que permitem fazer isso:

  • A API User Timing
  • A API console.timeStamp

A API User Timing

É possível usar performance.mark e performance.measure para adicionar as entradas da seguinte maneira:


// 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"]
      ],
    }
  }
});

Isso vai resultar na faixa Componentes adicionada à sua linha do tempo com a medição:

A visualização de rastreamento do painel "Performance". Ela se concentra na faixa personalizada expandida chamada "Componentes", que contém uma medição chamada "Renderização de componentes".
Faixa personalizada no painel de desempenho.

Essa API permite adicionar as entradas ao buffer da linha do tempo de performance e mostrá-las na interface do painel Performance do DevTools.

Saiba mais sobre essa API e o objeto devtools nos documentos.

A API console.timeStamp

Essa API é uma alternativa leve à API User Timing. Usando o mesmo exemplo de antes, você pode ter:


// 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"
);

Essa API oferece um método de alta performance para instrumentar aplicativos. Ao contrário da alternativa User Timing API, ela não cria dados armazenados em buffer. Essa API adiciona dados exclusivamente ao painel **Performance** no DevTools. Isso significa que, quando o DevTools não está gravando um rastreamento, as chamadas para a API não fazem nada, tornando-a significativamente mais rápida e adequada para caminhos ativos sensíveis ao desempenho. A opção de usar argumentos posicionais em vez de um objeto que contém todos os parâmetros de personalização também tem o objetivo de manter a API o mais leve possível.

Saiba mais sobre como usar o console.timeStamp para estender o painel "Performance" e os parâmetros que podem ser transmitidos na documentação.

Como o Angular integrou a API de extensibilidade do DevTools

Vamos analisar como a equipe do Angular usou a API de extensibilidade para integrar ao Chrome DevTools.

Evitar o overhead com console.timestamp

A instrumentação do Angular com a API de extensibilidade do painel Performance está disponível a partir da versão 20. O nível de granularidade desejado para os dados de performance no DevTools exige uma API rápida. Por isso, a solicitação de pull (60217) que adicionou a instrumentação optou por usar a API console.timeStamp. Isso evita que o desempenho do tempo de execução do aplicativo seja afetado pela possível sobrecarga da API de criação de perfil.

Dados instrumentados

Para fornecer uma boa ideia de qual código Angular está sendo executado e por que ele está sendo executado, várias partes dos pipelines de inicialização e renderização são instrumentadas, incluindo:

  • Inicialização de aplicativos e componentes.
  • Criação e atualizações de componentes.
  • Execução de listeners de eventos e hooks de ciclo de vida.
  • Muitos outros (por exemplo, criação dinâmica de componentes e renderização de blocos adiada).

Codificação por cores

A codificação por cores é usada para sinalizar ao desenvolvedor a categoria em que uma determinada entrada de métrica se enquadra. Por exemplo, as cores usadas para as entradas que marcam a execução do código TypeScript criado pelo desenvolvedor são diferentes das cores usadas para o código produzido pelo compilador Angular.

Na captura de tela a seguir, você pode ver como isso resulta em pontos de entrada (como detecção de mudanças e processamento de componentes) em azul, código gerado em roxo e código TypeScript (como listeners de eventos e hooks) renderizado em verde.

A visualização de rastreamento do painel "Performance". Ele se concentra na faixa personalizada expandida chamada "Angular", que contém um gráfico de chamas com medições de cores diferentes que representam a atividade de tempo de execução de um app Angular de maneira amigável para desenvolvedores.
Codificação de cores no painel "Performance".

O argumento de cor transmitido à API não é um valor de cor CSS, mas um token semântico mapeado para uma cor que corresponde à interface do DevTools. Os valores possíveis são primary, secondary e tertiary, com as respectivas variantes -dark e -light, além de uma cor error.

Músicas

No momento da redação, todos os dados de tempo de execução do Angular são adicionados à mesma faixa (rotulada como "🅰️ Angular"). No entanto, é possível adicionar várias faixas ao rastreamento e até mesmo agrupá-las. Por exemplo, considerando as seguintes chamadas para a API 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");

Os dados seriam organizados em faixas da seguinte maneira:

A visualização de rastreamento do painel "Performance". Ele se concentra nas várias faixas personalizadas expandidas, cada uma com diferentes medições internas.
Várias faixas personalizadas no painel "Performance".

Usar faixas separadas pode ser útil, por exemplo, quando você tem atividades assíncronas, vários jobs sendo executados em paralelo ou apenas grupos de atividades distintos o suficiente para serem separados em diferentes áreas da interface.

Por que isso é importante para desenvolvedores do Angular

O objetivo dessa integração direta é oferecer uma experiência de análise de performance mais intuitiva e abrangente. Ao mostrar os dados internos de performance do Angular diretamente no painel **Performance**, os desenvolvedores vão ter:

  • Visibilidade aprimorada: torna visíveis no cronograma mais amplo do navegador eventos de performance específicos do Angular, como renderização de componentes, ciclos de detecção de mudanças e muito mais.
  • Melhor compreensão: com informações ricas em contexto sobre os processos internos do Angular, ajudando você a identificar gargalos de desempenho com mais eficiência.

Ativar a integração

O uso da API de extensibilidade está oficialmente disponível em builds de desenvolvimento a partir da versão 20 do Angular. Para ativar, execute o utilitário global `ng.enableProfiling()` no seu app ou no console do DevTools. Para mais informações sobre a integração, consulte a [documentação do Angular](https://angular.dev/best-practices/profiling-with-chrome-devtools).

Outras considerações

Algumas considerações importantes a serem levadas em conta.

Mapas de origem e código minificado:

Os mapas de origem são uma ferramenta amplamente adotada que visa preencher a lacuna entre o código agrupado / minificado e a contraparte criada. Portanto…

Os mapas de origem não deveriam resolver o problema do código minificado em apps agrupados?

Embora os mapas de origem sejam úteis, eles não eliminam completamente os desafios ao criar perfis de apps da Web minificados complexos. Os mapas de origem permitem que o DevTools mapeie o código minificado de volta para o código-fonte original, facilitando a depuração. No entanto, confiar apenas nos mapas de origem para análise de desempenho ainda pode apresentar algumas limitações. Por exemplo, escolher a maneira como os internos da estrutura e o código criado são separados visualmente é complicado apenas com mapas de origem. Por outro lado, a API de extensibilidade oferece a flexibilidade para alcançar essa distinção e apresentá-la da maneira que o desenvolvedor considera mais conveniente.

Extensões do Chrome DevTools:

As extensões do Chrome que usam a API DevTools são uma ferramenta muito usada para estender o DevTools.

Os criadores de perfil dedicados (por exemplo, extensões do Chrome DevTools) são desnecessários ou desencorajados agora que essa API está disponível?

Não, essa API não foi criada para substituir ou desencorajar o desenvolvimento de criadores de perfis dedicados, como as extensões do Chrome DevTools. Eles ainda podem oferecer recursos, visualizações e fluxos de trabalho especializados adaptados a necessidades específicas. A API de extensibilidade do painel Performance tem como objetivo criar uma integração perfeita de dados personalizados com as visualizações do navegador no painel Performance.

O caminho a seguir

A perspectiva da API de extensibilidade.

Trabalhar com mais frameworks e abstrações

Estamos animados com outros frameworks e abstrações que adotam a API para melhorar a experiência de criação de perfil dos desenvolvedores. O React, por exemplo, implementou uma adoção experimental da API para o framework. Essa instrumentação mostra a renderização de componentes do cliente e do servidor, além de dados das APIs de programação do React. Saiba mais sobre isso e como ativar na página do React.

Builds de produção

Um dos objetivos dessa API é trabalhar com frameworks e provedores de abstração em geral para adotar e ativar a instrumentação em builds de produção. Isso pode ter um grande impacto no desempenho dos apps desenvolvidos com essas abstrações, já que os desenvolvedores podem criar um perfil do aplicativo da maneira como os usuários o usam. Acreditamos que a API console.timeStamp permite isso, considerando a velocidade e a baixa sobrecarga. No entanto, no momento, os frameworks ainda estão testando a API e investigando quais tipos de instrumentações são mais escalonáveis e úteis para os desenvolvedores.