Saiba como usar o Chrome e DevTools para encontrar problemas de memória que afectam o desempenho da página, incluindo fugas de memória, inchaço da memória, e frequentes recolhas de lixo.
Sumário #
- Descubra quanta memória a sua página está a usar actualmente com o Gestor de Tarefas Chrome.
- Visualize a utilização de memória ao longo do tempo com gravações da Linha do Tempo.
- Identificar árvores DOM separadas (uma causa comum de fugas de memória) com Heap Snapshots.
- Incobrir quando nova memória está a ser alocada no seu JS heap com gravações da Linha do Tempo de Alocação.
Overvisão #
No espírito do modelo de desempenho RAIL, o foco dos seus esforços de desempenho deve ser os seus utilizadores.
As questões de memória são importantes porque são frequentemente perceptíveis pelos utilizadores. Os utilizadores podem perceber problemas de memória das seguintes formas:
- O desempenho de uma página fica progressivamente pior com o tempo. Isto é possivelmente um sintoma de uma fuga de memória. Uma fuga de memória é quando um bug na página faz com que a página utilize progressivamente mais e mais memória ao longo do tempo.
- O desempenho de uma página é consistentemente mau. Isto é possivelmente um sintoma de inchaço da memória. O inchaço da memória é quando uma página utiliza mais memória do que a necessária para a velocidade óptima da página.
- O desempenho de uma página é atrasado ou parece fazer uma pausa frequente. Isto é possivelmente um sintoma de recolhas de lixo frequentes. A recolha de lixo é quando o navegador recupera a memória. O navegador decide quando isto acontece. Durante as recolhas, toda a execução do script é pausada. Portanto, se o navegador estiver a recolher muito lixo, a execução de scripts vai ser pausada muito.
Memory bloat: quanto é “demasiado”? #
Uma fuga de memória é fácil de definir. Se um site estiver progressivamente a utilizar cada vez mais memória, então tem uma fuga de memória. Mas o inchaço da memória é um pouco mais difícil de fixar. O que se qualifica como “usar demasiada memória”?
Não há números difíceis aqui, porque dispositivos e navegadores diferentes têm capacidades diferentes. A mesma página que corre sem problemas num smartphone de gama alta pode falhar num smartphone de gama baixa.
A chave aqui é usar o modelo RAIL e concentrar-se nos seus utilizadores. Descubra que dispositivos são populares entre os seus utilizadores, e depois teste a sua página nesses dispositivos. Se a experiência for consistentemente má, a página pode estar a exceder as capacidades de memória desses dispositivos.
Monitor memory use in realtime with the Chrome Task Manager #
Utilizar o Chrome Task Manager como ponto de partida para a sua investigação de problemas de memória. O Gestor de Tarefas é um monitor em tempo real que lhe diz quanta memória uma página está a utilizar actualmente.
-
Pressione Shift+Esc ou vá ao menu principal do Chrome e seleccione Mais ferramentas > Gestor de tarefas para abrir o Gestor de Tarefas.
-
clique direito sobre o cabeçalho da tabela do Gestor de Tarefas e active a memória JavaScript.
Estas duas colunas dizem-lhe coisas diferentes sobre como a sua página está a utilizar a memória:
- A coluna Memória representa a memória nativa. Os nós DOM são armazenados na memória nativa. Se este valor estiver a aumentar, os nós DOM estão a ser criados.
- A coluna Memória JavaScript representa a pilha JS. Esta coluna contém dois valores. O valor que lhe interessa é o número ao vivo (o número entre parênteses). O número em tempo real representa quanta memória os objectos alcançáveis na sua página estão a utilizar. Se este número estiver a aumentar, ou novos objectos estão a ser criados, ou os objectos existentes estão a crescer.
Visualizar fugas de memória com gravações da Linha do Tempo #
P>Pode também usar o painel da Linha do Tempo como outro ponto de partida na sua investigação. O painel da Linha do Tempo ajuda-o a visualizar a utilização da memória de uma página ao longo do tempo.
- Abrir o painel da Linha do Tempo em DevTools.
- Ativar a caixa de verificação Memória.
- Fazer uma gravação.
Tip: É uma boa prática iniciar e terminar a sua gravação com uma recolha forçada de lixo. Clique no botão de recolha de lixo () enquanto grava para forçar a recolha de lixo.
Para demonstrar gravações de memória da Linha do Tempo, 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);
Cada vez que o botão referido no código é premido, dez mil div
nós são anexados ao corpo do documento, e uma sequência de um milhão x
caracteres são empurrados para o x
matriz. A execução deste código produz uma gravação da Linha do Tempo como a seguinte captura de ecrã:
P>Primeiro, uma explicação da interface do utilizador. O gráfico HEAP no painel Síntese (abaixo de NET) representa a pilha do JS. Abaixo do painel de Visão Geral está o painel do contador. Aqui pode ver a utilização da memória repartida por pilha JS (o mesmo que o gráfico HEAP no painel Resumo), documentos, nós DOM, ouvintes, e memória GPU. Desactivar uma caixa de verificação esconde-a do gráfico.
Agora, uma análise do código comparada com a imagem do ecrã. Se olharmos para o contador de nós (o gráfico verde) podemos ver que ele corresponde perfeitamente com o código. A contagem do nó aumenta em passos discretos. Pode presumir que cada aumento na contagem do nó é uma chamada para grow()
. O gráfico do JS heap (o gráfico azul) não é tão simples. De acordo com as melhores práticas, a primeira imersão é na realidade uma recolha forçada de lixo (conseguida premindo o botão de recolha de lixo). À medida que a gravação avança, é possível ver que o tamanho da pilha de lixo JS aumenta. Isto é natural e esperado: o código JavaScript está a criar os nós DOM em cada clique no botão e a fazer muito trabalho quando cria a cadeia de um milhão de caracteres. O essencial aqui é o facto de a pilha de JS terminar mais alto do que começou (o “início” aqui é o ponto após a recolha forçada de lixo). No mundo real, se se visse este padrão de aumento do tamanho do JS heap ou do tamanho do nó, isso significaria potencialmente uma fuga de memória.
Descobrir fugas de memória da árvore DOM destacada com Heap Snapshots #
Um nó DOM só pode ser recolhido quando não há referências a ele nem da árvore DOM da página nem do código JavaScript. Diz-se que um nó é “destacado” quando é removido da árvore DOM mas algum JavaScript ainda faz referência a ele. Os nós DOM destacados são uma causa comum de fugas de memória. Esta secção ensina-lhe como usar os perfis de pilha DevTools para identificar nós destacados.
p>Aqui está um exemplo simples de nós DOM destacados.
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);
Cortar o botão referenciado no código cria um ul
nó com dez li
crianças. Estes nós são referenciados pelo código mas não existem na árvore DOM, por isso são destacados.
Fotografias do monte são uma forma de identificar nós destacados. Como o nome implica, os instantâneos heap mostram como a memória é distribuída entre os objectos JS da sua página e os nós DOM no momento da fotografia.
Para criar um instantâneo, abra DevTools e vá ao painel Perfis, seleccione o botão de rádio Take Heap Snapshot, e depois prima o botão Take Snapshot.
O instantâneo pode demorar algum tempo a processar e carregar. Uma vez terminado, seleccione-o do painel da esquerda (chamado HEAP SNAPSHOTS).
Type Detached
na caixa de texto do filtro de classe para procurar por árvores DOM destacadas.
Expandir os quilates para investigar uma árvore descolada.
Nós destacados a amarelo têm referências directas a eles a partir do código JavaScript. Os nós destacados a vermelho não têm referências directas. Só estão vivos porque fazem parte da árvore do nó amarelo. De um modo geral, pretende concentrar-se nos nós amarelos. Fixe o seu código para que o nó amarelo não esteja vivo durante mais tempo do que o necessário, e também se livre dos nós vermelhos que fazem parte da árvore do nó amarelo.
Clique num nó amarelo para o investigar mais a fundo. No painel Objectos pode ver mais informação sobre o código que o está a referenciar. Por exemplo, na imagem abaixo pode ver que a variável detachedTree
está a referenciar o nó. Para corrigir esta fuga de memória particular, estudaria o código que usa detachedTree
e asseguraria que remove a sua referência ao nó quando este já não é necessário.
h2>Identificar fugas de memória do JS heap com as linhas de tempo de alocação #
A linha de tempo de alocação é outra ferramenta que pode ajudá-lo a localizar fugas de memória no seu JS heap.
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);
A cada vez que o botão referenciado no código é premido, uma cadeia de um milhão de caracteres é adicionada à matriz x
.
Para gravar uma Linha de Tempo de Alocação, abra DevTools, vá ao painel Perfis, seleccione o botão de rádio Record Allocation Timeline, prima o botão Start, execute a acção que suspeita estar a causar a fuga de memória, e depois prima o botão stop recording () quando tiver terminado.
Como está a gravar, repare se aparecer alguma barra azul na Linha de Tempo de Atribuição, como na imagem de ecrã abaixo.
Essas barras azuis representam novas atribuições de memória. Essas novas alocações de memória são os seus candidatos a fugas de memória. Pode ampliar uma barra para filtrar o painel Construtor para mostrar apenas objectos que foram alocados durante o período de tempo especificado.
Expandir o objecto e clicar no seu valor para ver mais detalhes sobre ele no painel Objecto. Por exemplo, na imagem abaixo, ao visualizar os detalhes do objecto que foi recentemente atribuído, poderá ver que foi atribuído ao x
variável no Window
escopo.
Investigar alocação de memória por função #
Utilizar o tipo de Perfis de Alocação de Registos para ver a alocação de memória por função JavaScript.
- Seleccionar o botão de rádio Profiler de Alocação de Registos. Se houver um trabalhador na página, pode seleccioná-lo como alvo de perfil utilizando o menu pendente junto ao botão Iniciar.
>li>Pressione o botão Iniciar.li>Realizar as acções na página que pretende investigar.li>Pressione o botão Parar quando tiver terminado todas as suas acções.
DevTools mostra uma repartição da alocação de memória por função. A vista padrão é Heavy (Bottom Up), que mostra as funções que alocaram mais memória no topo.
h2>Spot frequently garbage collect #
Se a sua página aparecer a pausar frequentemente, então poderá ter problemas de recolha de lixo.
P>Pode usar ou o Gestor de Tarefas Cromado ou as gravações de memória da Linha do Tempo para detectar recolhas de lixo frequentes. No Gestor de Tarefas, os valores da Memória ou da Memória JavaScript, que sobem e descem frequentemente, representam recolhas de lixo frequentes. Nas gravações da Linha de Tempo, os gráficos de contagem de pilhas ou nós JS que sobem e descem frequentemente indicam recolhas de lixo frequentes.
Após ter identificado o problema, pode utilizar uma gravação da Linha de Tempo de Alocação para descobrir onde a memória está a ser alocada e que funções estão a causar as alocações.