Corrigir problemas de memória

Kayce Basques
Kayce Basques

Aprenda a usar o Chrome e o DevTools para encontrar problemas de memória que afetam o desempenho da página, incluindo: vazamentos e sobrecarga de memória e coletas de lixo frequentes.

Resumo

  • Descubra quanta memória sua página está usando no momento com o Gerenciador de tarefas do Chrome.
  • Confira o uso da memória ao longo do tempo com os registros da Linha do tempo.
  • Identifique árvores do DOM desconectadas (uma causa comum de vazamentos de memória) com instantâneos de pilha.
  • Descubra quando nova memória é alocada a sua heap JS com os registros da Allocation Linha do tempo.

Visão geral

De acordo com o modelo de desempenho RAIL, o foco dos seus esforços de desempenho deve ser seus usuários.

Os problemas de memória são importantes porque muitas vezes são perceptíveis pelos usuários. Os usuários percebem a memória problemas das seguintes maneiras:

  • O desempenho de uma página piora progressivamente ao longo do tempo. Isso é possivelmente um sintoma de vazamento de memória. Um vazamento de memória é quando um bug na página faz com que ela use mais e mais memória com o tempo.
  • O desempenho de uma página é consistentemente ruim. Isso é possivelmente um sintoma de ocupação excessiva da memória. Memória A ocupação excessiva é quando uma página usa mais memória do que o necessário para obter a velocidade ideal.
  • O desempenho de uma página atrasa ou parece pausar com frequência. Isso é um sintoma de coletas de lixo frequentes. A coleta de lixo ocorre quando o navegador recupera a memória. O navegador decide quando isso acontece. Durante as coletas, toda a execução do script é pausada. Então, se o navegador estiver coletando muito lixo, a execução do script será pausada muitas vezes.

Excesso de memória: quanto é "demais"?

É fácil definir um vazamento de memória. Se um site está usando cada vez mais memória, você precisa vazaram. Mas a ocupação excessiva da memória é um pouco mais difícil de detectar. O que se qualifica como "uso excessivo de memória"?

Não há números fixos aqui, porque dispositivos e navegadores diferentes têm recursos diferentes. A mesma página que é executada suavemente em um smartphone sofisticado pode falhar em um smartphone mais simples.

A chave aqui é usar o modelo RAIL e focar nos seus usuários. Descubra quais dispositivos são mais usados com os usuários e, em seguida, testar a página nesses dispositivos. Se a experiência for consistente a página pode estar excedendo os recursos de memória do dispositivo.

Monitorar o uso da memória em tempo real com o gerenciador de tarefas do Chrome

Use o Gerenciador de tarefas do Chrome como ponto de partida na investigação de problemas de memória. Gerenciador de tarefas é um monitor em tempo real que informa quanta memória uma página está usando no momento.

  1. Pressione Shift+Esc ou acesse o menu principal do Chrome e selecione Mais ferramentas > Gerenciador de tarefas para abra o Gerenciador de tarefas.

    Como abrir o Gerenciador de tarefas

  2. Clique com o botão direito do mouse no cabeçalho da tabela do gerenciador de tarefas e ative a memória JavaScript.

    Como ativar a memória do JS

Essas duas colunas contêm informações diferentes sobre como sua página está usando a memória:

  • A coluna Memória representa a memória nativa. Os nós DOM são armazenados na memória nativa. Se esse está aumentando, os nós DOM estão sendo criados.
  • A coluna Memória JavaScript representa a heap JS. Essa coluna contém dois valores. A o valor em que você está interessado é o número ativo (o número entre parênteses). O número ativo representa a quantidade de memória que os objetos acessíveis da página estão usando. Se este número for estão aumentando, novos objetos estão sendo criados ou os atuais estão crescendo.

Visualize vazamentos de memória com os registros de desempenho

Você também pode usar o painel "Desempenho" como outro ponto de partida na sua investigação. Desempenho ajuda a visualizar o uso de memória por uma página ao longo do tempo.

  1. Abra o painel Desempenho no DevTools.
  2. Marque a caixa de seleção Memória.
  3. Fazer uma gravação.
.

Para demonstrar os registros de memória de performance, considere o código abaixo:

var x = [];

function grow() {
  for (var i = 0; i < 10000; i++) {
    document.body.appendChild(document.createElement('div'));
  }
  x.push(new Array(1000000).join('x'));
}

document.getElementById('grow').addEventListener('click', grow);

Sempre que o botão referenciado no código é pressionado, 10 mil nós div são anexados ao corpo do documento, e uma string de um milhão de caracteres x é enviada para a matriz x. A execução desse código produz uma gravação da linha do tempo como a seguinte captura de tela:

exemplo de crescimento simples

Primeiro, uma explicação sobre a interface do usuário. O gráfico HEAP no painel Overview (abaixo) NET) representa a heap JS. Abaixo do painel Visão geral fica o painel Contador. Aqui é possível Confira o uso da memória detalhado pela heap do JS (igual ao gráfico HEAP no painel Overview). documentos, nós do DOM, listeners e memória GPU. Quando você desativa uma caixa de seleção, ela fica oculta no gráfico.

Agora, uma análise do código comparada com a captura de tela. Se você observar o contador de nós (a gráfico verde), vai notar que ele corresponde perfeitamente ao código. A contagem de nós aumenta em etapas distintas. É possível presumir que cada aumento na contagem de nós seja uma chamada para grow(). O JavaScript gráfico de heap (o gráfico azul) não é tão simples. De acordo com as práticas recomendadas, a primeira queda é, na verdade, uma coleta de lixo forçada (alcançada ao pressionar o botão collect lixeira). Conforme durante a gravação, observe que o tamanho do heap do JS aumenta. Isso é natural e esperado: a O código JavaScript está criando os nós DOM em cada clique de botão e fazendo muito trabalho quando cria a sequência de um milhão de caracteres. O principal aqui é o fato de que a heap JS termina maior do que começou (o "início" é o ponto após a coleta de lixo forçada). Em No mundo real, se você visse esse padrão de aumento do tamanho do heap do JS ou do nó, isso pode ser um vazamento de memória.

Descubra vazamentos de memória da árvore do DOM desconectada com instantâneos de pilha

Um nó DOM só pode ser coletado como lixo quando não houver referências a ele do nó árvore do DOM ou código JavaScript. Um nó é considerado "desanexado" quando é removido da árvore do DOM, mas algum JavaScript ainda faz referência a ele. Nós do DOM desconectados são uma causa comum de vazamentos de memória. Isso ensina a usar o DevTools criadores de perfil de alocação heap para identificar nós desconectados.

Veja a seguir um exemplo simples de nós do DOM desconectados.

var detachedTree;

function create() {
  var ul = document.createElement('ul');
  for (var i = 0; i < 10; i++) {
    var li = document.createElement('li');
    ul.appendChild(li);
  }
  detachedTree = ul;
}

document.getElementById('create').addEventListener('click', create);

Clicar no botão referenciado no código cria um nó ul com dez filhos li. Esses nós são referenciados pelo código, mas não existem na árvore do DOM e, portanto, são desconectados.

Os snapshots de heap são uma maneira de identificar nós desconectados. Como o nome indica, os resumos de pilha mostram como a memória é distribuída entre os objetos JS e nós do DOM da página no momento da snapshot.

Para criar um snapshot, abra o DevTools e acesse o painel Memory, selecione a opção Heap Snapshot e pressione o botão Take Snapshot.

criar instantâneo de alocação heap

O processamento e o carregamento do snapshot podem levar algum tempo. Quando terminar, selecione-o no menu chamado HEAP SNAPSHOTS.

Digite Detached na caixa de texto Filtro de classe para pesquisar árvores do DOM desconectadas.

filtragem de nós desconectados

Expanda os quilates para investigar uma árvore desconectada.

investigando árvore independente

Os nós destacados em amarelo fazem referência direta a eles no código JavaScript. Nós destacados vermelhos não têm referências diretas. Eles só estão vivos porque são parte do nó árvore. Em geral, convém se concentrar nos nós amarelos. Corrija o código para que o nó amarelo não fique ativos por mais tempo do que o necessário e também se livrará dos nós vermelhos que fazem parte da árvore do nó amarelo.

Clique em um nó amarelo para investigar melhor. No painel Objetos, é possível visualizar mais sobre o código que faz referência a ele. Por exemplo, na captura de tela abaixo, que a variável detachedTree está fazendo referência ao nó. Para corrigir esse vazamento de memória, estudaria o código que usa detachedTree e garantiria que ele remove a referência dele ao nó. quando não forem mais necessários.

investigar um nó amarelo

Identifique vazamentos de memória de heap JS com as linhas do tempo de alocação

A Allocation Linha do tempo é outra ferramenta que pode ajudá-lo a rastrear vazamentos de memória na pilha JS.

Para demonstrar a linha do tempo de alocação, considere o seguinte código:

var x = [];

function grow() {
  x.push(new Array(1000000).join('x'));
}

document.getElementById('grow').addEventListener('click', grow);

Toda vez que o botão referenciado no código é pressionado, uma string de um milhão de caracteres é foi adicionado à matriz x.

Para gravar uma Allocation Linha do tempo, abra o DevTools, acesse o painel Profiles, selecione a opção Record Botão de opção Allocation Linha do tempo, pressione o botão Iniciar e realize a ação suspeita está causando o vazamento de memória, e depois pressione o botão Parar gravação. (botão &quot;Parar gravação&quot;) quando e pronto.

Enquanto está gravando, observe se alguma barra azul aparece na linha do tempo da alocação, como no captura de tela abaixo.

novas alocações

Essas barras azuis representam novas alocações de memória. Essas novas alocações de memória são as candidatas vazamentos de memória. É possível aplicar zoom a uma barra para filtrar o painel Construtor e mostrar apenas os objetos que foram alocados durante o período especificado.

linha do tempo de alocação com zoom ampliado

Expanda o objeto e clique no valor dele para ver mais detalhes sobre ele no painel Objeto. Para na captura de tela abaixo, ao conferir os detalhes do objeto recém-alocado, é possível conferir que ela foi alocada à variável x no escopo Window.

detalhes do objeto

Investigar a alocação de memória por função

Use o tipo Amostragem de alocação no painel Memória para visualizar a alocação de memória por função do JavaScript.

Criador de perfil de alocação de registro

  1. Selecione o botão de opção Amostragem de alocação. Se houver um worker na página, pode selecioná-lo como o destino de criação de perfil usando o menu suspenso ao lado do botão Start.
  2. Pressione o botão Start.
  3. Execute as ações na página que você quer investigar.
  4. Pressione o botão Parar quando tiver concluído todas as ações.

O DevTools mostra um detalhamento da alocação de memória por função. A visualização padrão é grossa (inferior) para cima), que exibe as funções que alocaram mais memória na parte de cima.

Perfil de alocação

Identificar coletas de lixo frequentes

Se a página parece pausar com frequência, é possível que você tenha problemas com a coleta de lixo.

Você pode usar o gerenciador de tarefas do Chrome ou os registros de memória da linha do tempo para identificar lixo frequente . No gerenciador de tarefas, aumenta e diminui frequentemente a Memória ou Memória JavaScript. representam coletas de lixo frequentes. Nas gravações da Linha do tempo, com frequência aumentando e diminuindo Os gráficos de heap ou contagem de nós do JS indicam coletas de lixo frequentes.

Depois de identificar o problema, você pode usar uma gravação da linha do tempo de alocação para descobrir onde que a memória está sendo alocada e quais funções estão causando as alocações.