Registrar instantâneos de heap usando a ferramenta Memória
Use o criador de perfil heap na ferramenta Memória para fazer o seguinte:
- Registre instantâneos de heap do JavaScript (heap JS).
- Analisar grafos de memória.
- Comparar instantâneos.
- Encontre vazamentos de memória.
O criador de perfil de heap DevTools mostra a distribuição de memória usada pelos objetos JavaScript e por nós DOM relacionados na página da Web renderizada.
Pegue um instantâneo
Abra a página da Web que você deseja analisar. Por exemplo, abra a página de demonstração de objetos dispersos em uma nova janela ou guia.
Para abrir o DevTools, clique com o botão direito do mouse na página da Web e selecione Inspecionar. Ou pressione Ctrl+Shift+I (Windows, Linux) ou Command+Option+I (macOS). DevTools é aberto.
Em DevTools, na Barra de Atividades, selecione a guia Memória . Se essa guia não estiver visível, clique no botão Mais ferramentas (
).
Na seção Selecionar tipo de perfil, selecione o botão de opção Heap instantâneo.
Em Selecionar instância de VM JavaScript, selecione a VM JavaScript que você deseja perfilar.
Clique no botão Tomar instantâneo:
Depois que o heap instantâneo recém-gravado tiver sido carregado em DevTools e tiver sido analisado, o instantâneo será exibido e uma nova entrada será exibida na barra lateral Perfis em INSTANTÂNEOS heap:
O número abaixo do novo item da barra lateral mostra o tamanho total dos objetos JavaScript acessíveis. Para saber mais sobre os tamanhos do objeto no heap instantâneo, consulte Tamanhos e distâncias de objeto na terminologia memória.
O instantâneo exibe apenas os objetos do grafo de memória que são acessíveis do objeto global. Fazer um instantâneo sempre começa com uma coleta de lixo.
Pegue outro instantâneo
Para tirar outra instantâneo quando uma já estiver exibida na ferramenta Memória, na barra lateral, clique em Perfis acima do instantâneo existente:
Limpar instantâneos
Para limpar todos os instantâneos da ferramenta Memória , clique no ícone Limpar todos os perfis ():
Exibir instantâneos
Instantâneos de heap podem ser exibidos de várias maneiras diferentes na ferramenta Memória . Cada maneira de exibir um heap instantâneo na interface do usuário corresponde a uma tarefa diferente:
Exibir | Conteúdo | Use para |
---|---|---|
Resumo | Mostra objetos agrupados pelo nome do construtor. | Localizar objetos e a memória que eles usam, com base em tipos agrupados pelo nome do construtor. Útil para rastrear vazamentos do DOM. |
Comparação | Exibe as diferenças entre dois instantâneos. | Comparando dois instantâneos de memória (ou mais) de antes e depois de uma operação. Inspecionar o delta na memória liberada e inspecionar a contagem de referência ajuda você a confirmar a presença e a causa de um vazamento de memória e ajuda a determinar sua causa. |
Contenção | Permite a exploração de conteúdo de heap. | Fornece uma melhor exibição da estrutura do objeto, ajudando a analisar objetos referenciados no namespace global (janela) para descobrir o que está mantendo os objetos ao redor. Use-o para analisar fechamentos e mergulhar em seus objetos em um nível baixo. |
Para alternar entre exibições, use a lista suspensa na parte superior da ferramenta Memória :
Observação
Nem todas as propriedades são armazenadas no heap JavaScript. As propriedades implementadas usando getters que executam código nativo não são capturadas. Além disso, valores que não são de cadeia de caracteres, como números, não são capturados.
Exibição resumida
Inicialmente, um instantâneo de heap é aberto na exibição Resumo, que exibe uma lista de construtores:
Cada construtor na lista pode ser expandido para mostrar os objetos que foram instanciados usando esse construtor.
Para cada construtor na lista, a exibição Resumo também mostra um número como ×123, indicando o número total de objetos criados com o construtor. A exibição Resumo também mostra as seguintes colunas:
Nome da coluna | Descrição |
---|---|
Distância | Exibe a distância até a raiz usando o caminho mais curto e simples de nós. Consulte Distância na terminologia memória. |
Tamanho superficial | Exibe a soma de tamanhos rasos de todos os objetos criados por uma determinada função de construtor. O tamanho superficial é o tamanho do heap JavaScript que é mantido diretamente por um objeto. O tamanho superficial de um objeto geralmente é pequeno, porque um objeto JavaScript geralmente armazena apenas sua descrição do objeto, não os valores, na memória diretamente mantida do objeto. A maioria dos objetos JavaScript armazena seus valores em um repositório de suporte que está em outro lugar no heap JavaScript e expõe apenas um pequeno objeto wrapper na parte do heap JavaScript que pertence diretamente ao objeto. Consulte Tamanho superficial na terminologia memória. |
Tamanho retido | Exibe o tamanho máximo retido entre o mesmo conjunto de objetos. O tamanho da memória que você pode liberar depois que um objeto é excluído (e os dependentes não são mais acessíveis) é chamado de tamanho retido. Consulte Tamanho retido na terminologia memória. |
Depois de expandir um construtor na exibição Resumo , todas as instâncias do construtor são exibidas. Para cada instância, os tamanhos rasos e retidos são exibidos nas colunas correspondentes. O número após o @
caractere é a ID exclusiva do objeto, permitindo que você compare instantâneos de heap por objeto.
Entradas do construtor na exibição Resumo
A exibição Resumo na ferramenta Memória lista grupos de construtores de objetos:
Os grupos de construtores na exibição Resumo podem ser funções internas, como Array
ou Object
ou podem ser funções definidas em seu próprio código.
Para revelar a lista de objetos que foram instanciados por um determinado construtor, expanda o grupo de construtores.
Nomes de categoria especiais na exibição Resumo
A exibição Resumo também contém nomes de categoria especiais que não se baseiam em construtores. Estas categorias especiais são:
Nome da categoria | Descrição |
---|---|
(matriz) | Vários objetos internos semelhantes à matriz que não correspondem diretamente a objetos visíveis do JavaScript, como o conteúdo de matrizes JavaScript ou as propriedades nomeadas de objetos JavaScript. |
(código compilado) | Dados internos que o V8 (mecanismo JavaScript do Microsoft Edge) precisa executar funções definidas por JavaScript ou WebAssembly. O V8 gerencia automaticamente o uso de memória nesta categoria: se uma função for executada muitas vezes, o V8 usará mais memória para essa função para que a função seja executada mais rapidamente. Se uma função não for executada há algum tempo, o V8 poderá excluir os dados internos dessa função. |
(cadeia de caracteres concatenada) | Quando duas cadeias de caracteres são concatenadas juntas, como ao usar o operador JavaScript + , o V8 pode optar por representar o resultado internamente como uma cadeia de caracteres concatenada. Em vez de copiar todos os caracteres das duas cadeias de caracteres em uma nova cadeia de caracteres, o V8 cria um objeto pequeno que aponta para as duas cadeias de caracteres. |
InternalNode | Objetos alocados fora do V8, como objetos C++ definidos pelo Blink, o mecanismo de renderização do Microsoft Edge. |
(forma do objeto) | Informações sobre objetos, como o número de propriedades que eles têm e uma referência aos protótipos, que o V8 mantém internamente quando os objetos são criados e atualizados. Isso permite que o V8 represente com eficiência objetos com as mesmas propriedades. |
(cadeia de caracteres fatiada) | Ao criar uma substring, como ao usar o método JavaScript substring , o V8 pode optar por criar um objeto de cadeia de caracteres fatiado em vez de copiar todos os caracteres relevantes da cadeia de caracteres original. Este novo objeto contém um ponteiro para a cadeia de caracteres original e descreve qual intervalo de caracteres da cadeia de caracteres original a ser usada. |
system /Context | Variáveis locais de um escopo JavaScript que podem ser acessadas por alguma função aninhada. Cada instância de função contém um ponteiro interno para o contexto no qual ela é executada, para que ela possa acessar essas variáveis. |
(sistema) | Vários objetos internos que ainda não foram categorizados de forma mais significativa. |
Exibição de comparação
Para localizar objetos vazados, compare vários instantâneos uns com os outros. Em um aplicativo Web, geralmente, fazer uma ação e, em seguida, a ação inversa não deve levar a mais objetos na memória. Por exemplo, ao abrir um documento e fechá-lo, o número de objetos na memória deve ser o mesmo que antes de abrir o documento.
Para verificar se determinadas operações não criam vazamentos:
Faça uma instantâneo de heap antes de executar uma operação.
Execute a operação. Ou seja, interaja com a página de alguma forma que possa estar causando um vazamento.
Execute a operação inversa. Ou seja, faça a interação oposta e repita-a algumas vezes.
Pegue um segundo instantâneo de heap.
No segundo heap instantâneo, altere a exibição para Comparação, comparando-a ao Instantâneo 1.
Na exibição Comparação , a diferença entre dois instantâneos é exibida:
Ao expandir um construtor na lista, as instâncias de objeto adicionadas e excluídas são mostradas.
Exibição de contenção
A exibição de contenção permite que você espie dentro de fechamentos de funções, observe objetos internos da VM (máquina virtual) que compõem seus objetos JavaScript e entenda a quantidade de memória que seu aplicativo usa em um nível muito baixo:
A exibição de contenção mostra os seguintes tipos de objetos:
Pontos de entrada de exibição de contenção | Descrição |
---|---|
Objetos DOMWindow | Objetos globais para código JavaScript. |
Raízes do GC | As raízes de GC usadas pelo coletor de lixo da máquina virtual JavaScript. As raízes do GC são compostas por mapas de objetos internos, tabelas de símbolos, pilhas de thread de VM, caches de compilação, escopos de identificador e identificadores globais. |
Objetos nativos | Objetos criados pelo navegador, como nós DOM e regras CSS, que são mostrados na máquina virtual JavaScript para permitir a automação. |
A seção Retentores
A seção Retentores é exibida na parte inferior da ferramenta Memória e mostra todos os objetos que apontam para o objeto selecionado. A seção Retentores é atualizada quando você seleciona um objeto diferente na exibição Resumo, Contenção ou Comparação .
Na captura de tela a seguir, um objeto de cadeia de caracteres foi selecionado na exibição Resumo e a seção Retentores mostra que a cadeia de caracteres é mantida pela x
propriedade de uma instância da Item
classe, encontrada no example-03.js
arquivo:
Ocultar ciclos
Na seção Retentores , ao analisar os objetos que mantêm o objeto selecionado, você poderá encontrar ciclos. Os ciclos ocorrem quando o mesmo objeto aparece mais de uma vez no caminho do retentor do objeto selecionado. Na seção Retentores , um objeto ciclizado é indicado por estar esmaecido.
Para ajudar a simplificar o caminho do retentor, ocultar ciclos na seção Retentores clicando no menu suspenso Filtrar bordas e selecionando Ocultar ciclo:
Ocultar nós internos
Nós internos são objetos específicos do V8 (o mecanismo JavaScript no Microsoft Edge).
Para ocultar nós internos da seção Retentores , no menu suspenso Filtrar bordas , selecione Ocultar interno.
Configurar a coluna Tamanho Superficial para incluir o tamanho de um objeto inteiro
Por padrão, a coluna Tamanho Superficial na ferramenta Memória inclui apenas o tamanho do objeto em si. O tamanho superficial é o tamanho do heap JavaScript que é mantido diretamente por um objeto. O tamanho superficial de um objeto geralmente é pequeno, porque um objeto JavaScript geralmente armazena apenas sua descrição do objeto, não os valores, na memória diretamente mantida do objeto. A maioria dos objetos JavaScript armazena seus valores em um repositório de suporte que está em outro lugar no heap JavaScript e expõe apenas um pequeno objeto wrapper na parte do heap JavaScript que pertence diretamente ao objeto. Por exemplo, as instâncias JavaScript Array
armazenam o conteúdo da matriz em um repositório de suporte, que é um local de memória separado que não está incluído no tamanho superficial da matriz.
Você pode configurar a coluna Tamanho Superficial para relatar todo o tamanho dos objetos, incluindo o tamanho do repositório de suporte do objeto.
Para incluir todo o tamanho dos objetos na coluna Tamanho Superficial :
Em DevTools, clique no botão Personalizar e controlar DevTools (
) e clique em Configurações (
). Ou, enquanto DevTools tem foco, pressione F1.
Na seção Experimentos , selecione a caixa de seleção Em instantâneos de heap, trate o tamanho do repositório de suporte como parte do objeto que contém.
Clique no botão Fechar (x) da página Configurações e clique no botão Recarregar DevTools .
Pegue um novo instantâneo de heap. A coluna Tamanho Superficial agora inclui todo o tamanho dos objetos:
Filtrar instantâneos de heap por tipos de nó
Use filtros para se concentrar em partes específicas de um instantâneo de heap. Ao examinar todos os objetos em um heap instantâneo na ferramenta Memória, pode ser difícil se concentrar em objetos específicos ou em caminhos de retenção.
Para se concentrar apenas em tipos específicos de nós, use o filtro Tipos de Nó , no canto superior direito. Por exemplo, para ver apenas as matrizes e objetos de cadeia de caracteres no heap instantâneo:
Para abrir o filtro Tipos de Nó , clique em Padrão no canto superior direito.
Selecione as entradas Matriz e Cadeia de Caracteres.
O heap instantâneo é atualizado para mostrar apenas os objetos de matriz e cadeia de caracteres:
Localizar um objeto específico
Para encontrar um objeto no heap coletado, você pode pesquisar usando Ctrl+F e fornecer a ID do objeto.
Descobrir vazamentos do DOM
A ferramenta Memória tem a capacidade de mostrar as dependências bidirecionais que às vezes existem entre objetos nativos do navegador (nós DOM, regras CSS) e objetos JavaScript. Isso ajuda a descobrir vazamentos de memória que acontecem devido a nós DOM desapegados esquecidos que permanecem na memória.
Considere a seguinte árvore DOM:
O exemplo de código a seguir cria as variáveis treeRef
JavaScript e leafRef
, que fazem referência a dois dos nós DOM na árvore:
// Get a reference to the #tree element.
const treeRef = document.querySelector("#tree");
// Get a reference to the #leaf element,
// which is a descendant of the #tree element.
const leafRef = document.querySelector("#leaf");
No exemplo de código a seguir, o <div id="tree">
elemento é removido da árvore DOM:
// Remove the #tree element from the DOM.
document.body.removeChild(treeRef);
O <div id="tree">
elemento não pode ser coletado porque a variável treeRef
JavaScript ainda existe. A treeRef
variável faz referência direta ao <div id="tree">
elemento. No exemplo de código a seguir, a treeRef
variável é anulada:
// Remove the treeRef variable.
treeRef = null;
O <div id="tree">
elemento ainda não pode ser coletado porque a variável leafRef
JavaScript ainda existe. A leafRef.parentNode
propriedade faz referência ao <div id="tree">
elemento. No exemplo de código a seguir, a leafRef
variável é anulada:
// Remove the leafRef variable.
leafRef = null;
Neste ponto, o <div id="tree">
elemento pode ser coletado com lixo. Ambos treeRef
e leafRef
devem primeiro ser anulados, para que toda a árvore DOM sob o <div id="tree">
elemento seja coletada em lixo.
Página da Web de demonstração: Exemplo 6: Vazamento de nós do DOM
Para entender onde os nós do DOM podem vazar e como detectar esse vazamento, abra o exemplo da página da Web exemplo 6: Vazamento de nós DOM em uma nova janela ou guia.
Página da Web de demonstração: Exemplo 9: vazamentos do DOM maiores do que o esperado
Para ver por que um vazamento do DOM pode ser maior do que o esperado, abra o exemplo da página da Web exemplo 9: o DOM vaza maior do que o esperado em uma nova janela ou guia.
Analisar o impacto dos fechamentos na memória
Para analisar o impacto dos fechamentos na memória, experimente este exemplo:
Abra a página da Web de demonstração do Eval is evil em uma nova janela ou guia.
Grave um instantâneo de heap.
Na página da Web renderizada, clique no botão Fechamentos com eval .
Grave um segundo instantâneo de heap.
Na barra lateral, o número abaixo do segundo instantâneo deve ser maior que o número abaixo do primeiro instantâneo. Isso indica que mais memória está sendo usada pela página da Web depois de clicar no botão Fechamentos com eval .
No segundo instantâneo de heap, altere a exibição para Comparação e compare o segundo instantâneo de heap com o primeiro instantâneo de heap.
A exibição Comparação mostra que novas cadeias de caracteres foram criadas no segundo heap instantâneo:
Na exibição Comparação, expanda o construtor (cadeia de caracteres).
Clique na primeira entrada (cadeia de caracteres).
A seção Retentores é atualizada e mostra que a
largeStr
variável mantém a cadeia de caracteres selecionada na exibição Comparação .A
largeStr
entrada é expandida automaticamente e mostra que a variável é mantida pelaeC
função, que é o fechamento em que a variável é definida:
Dica: nomeia funções para diferenciar entre fechamentos em um instantâneo
Para distinguir facilmente entre fechamentos JavaScript em um instantâneo de heap, forneça nomes de suas funções.
O exemplo a seguir usa uma função sem nome para retornar a largeStr
variável:
function createLargeClosure() {
const largeStr = 'x'.repeat(1000000).toLowerCase();
// This function is unnamed.
const lC = function() {
return largeStr;
};
return lC;
}
O exemplo a seguir nomeia a função, o que facilita a distinção entre fechamentos no heap instantâneo:
function createLargeClosure() {
const largeStr = 'x'.repeat(1000000).toLowerCase();
// This function is named.
const lC = function lC() {
return largeStr;
};
return lC;
}
Salvar e exportar cadeias de caracteres de um heap instantâneo para JSON
Ao usar um heap instantâneo na ferramenta Memória, você pode exportar todos os objetos de cadeia de caracteres do instantâneo para um arquivo JSON. Na ferramenta Memória , na seção Construtor , clique no botão Salvar tudo para arquivar ao lado da (string)
entrada:
A ferramenta Memória exporta um arquivo JSON que contém todos os objetos de cadeia de caracteres do heap instantâneo:
Confira também
- Terminologia de memória.
- Localizar e depurar vazamentos de memória no JavaScript com Chrome DevTools por Gonzalo Ruiz de Villa, que também se aplica ao Microsoft Edge DevTools.
Observação
Partes desta página são modificações baseadas no trabalho criado e compartilhado pelo Google e usadas de acordo com os termos descritos na Licença Internacional de Atribuição do Creative Commons 4.0. A página original é encontrada aqui e é de autoria de Meggin Kearney (Technical Writer).
Este trabalho é licenciado sob uma Licença Internacional de Atribuição do Creative Commons 4.0.
Comentários
https://aka.ms/ContentUserFeedback.
Brevemente: Ao longo de 2024, vamos descontinuar progressivamente o GitHub Issues como mecanismo de feedback para conteúdos e substituí-lo por um novo sistema de feedback. Para obter mais informações, veja:Submeter e ver comentários