Registre instantâneos de heap usando a ferramenta Memória (tipo de criação de perfil "Heap snapshot")

Use o criador de perfil de heap na ferramenta Memória para fazer o seguinte:

  • Registre instantâneos de heap do JavaScript (heap JS).
  • Analise grafos de memória.
  • Compare instantâneos.
  • Localizar 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.

Tire um snapshot

  1. Abra a página da Web que você deseja analisar. Por exemplo, abra a página de demonstração Objetos dispersos em uma nova janela ou guia.

  2. 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). O DevTools é aberto.

  3. No DevTools, na Barra de Atividades, selecione a guia Memória . Se essa guia não estiver visível, clique no botão Mais ferramentas (ícone de Mais ferramentas).

  4. Na seção Selecionar tipo de criação de perfil, selecione o botão de opção Heap snapshot.

  5. Em Select JavaScript VM instance, selecione a VM do JavaScript que você deseja criar o perfil.

  6. Clique no botão Tirar snapshot:

A ferramenta Memória, a opção Heap snapshot está selecionada e o botão Take snapshot está realçado

Depois que o snapshot de heap recém-gravado for carregado no DevTools e analisado, o snapshot será exibido e uma nova entrada será exibida na barra lateral Perfis em Instantâneos de heap:

Tamanho total de objetos alcançáveis

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 de objetos no snapshot de heap, consulte Tamanhos e distâncias de objetos na terminologia da memória.

O snapshot exibe apenas os objetos do gráfico de memória que podem ser acessados pelo objeto global. Tirar um snapshot sempre começa com uma coleta de lixo.

Tirar outro snapshot

Para tirar outro snapshot quando um já estiver exibido na ferramenta Memória, na barra lateral, clique em Perfis acima do snapshot existente:

O botão Perfis para tirar outro snapshot

Limpar instantâneos

Para limpar todos os instantâneos da ferramenta Memória , clique no ícone Limpar todos os perfis (o ícone Limpar):

Remover instantâneos

Exibir instantâneos

Os instantâneos de heap podem ser exibidos de várias maneiras diferentes na ferramenta Memória . Cada maneira de exibir um snapshot de heap na interface do usuário corresponde a uma tarefa diferente:

Exibir Conteúdo Use para
Resumo Mostra objetos agrupados por nome de construtor. Localizando objetos e a memória que eles usam, com base em tipos agrupados por nome de construtor. Útil para rastrear vazamentos de DOM.
Comparação Exibe as diferenças entre dois instantâneos. Comparando dois (ou mais) instantâneos de memória antes e depois de uma operação. Inspecionar o delta na memória liberada e inspecionar a contagem de referência ajuda 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 do conteúdo do heap. Fornece uma melhor visão da estrutura do objeto, ajudando a analisar objetos referenciados no namespace global (janela) para descobrir o que está mantendo os objetos por perto. Use-o para analisar fechamentos e mergulhar em seus objetos em um nível baixo.

Para alternar entre modos de exibição, use a lista suspensa na parte superior da ferramenta Memória :

Alternar seletor de modos de exibição

Itens omitidos de instantâneos de heap

As propriedades implementadas usando getters que executam código nativo não são capturadas no snapshot do heap, pois essas propriedades não são armazenadas no heap do JavaScript.

Valores que não são de cadeia de caracteres, como números, não são capturados.

Exibição resumida

A exibição Resumo na ferramenta Memória lista:

  • Grupos de construtores de objeto.
  • Nomes de categorias especiais, como (array),(compiled code) ou uma lista de propriedades como {foo, bar, baz}.

Inicialmente, um snapshot de heap é aberto na exibição Summary, que exibe uma lista de construtores:

Exibição resumida

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 simples mais curto dos nós. Consulte Distância na terminologia da memória.
Tamanho raso Exibe a soma dos tamanhos superficiais 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 backup que está em outro lugar no heap JavaScript e só expõe um pequeno objeto wrapper na parte do heap JavaScript que pertence diretamente ao objeto. Consulte Tamanho superficial na terminologia da 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 da memória.

Depois de expandir um construtor na visualizaçã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 comparar instantâneos de heap por objeto.

Entradas do construtor

A visualização Resumo na ferramenta Memória lista grupos de construtores de objetos:

Grupos de construtores

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 categorias especiais

A exibição Resumo na ferramenta Memória inclui os nomes de categoria especiais a seguir, que não são baseados em construtores. A maioria desses nomes de categoria é exibida entre parênteses.

Nome da categoria Descrição
(matriz) Vários objetos semelhantes a matrizes internas 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 para executar funções definidas por JavaScript ou WebAssembly. O V8 gerencia automaticamente o uso de memória nesta categoria: se uma função é executada muitas vezes, o V8 usa mais memória para essa função para que a função seja executada mais rapidamente. Se uma função não for executada durante um tempo, o V8 poderá excluir os dados internos para essa função.
(cadeia de caracteres concatenada) Quando duas cadeias de caracteres são concatenadas, 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 strings em uma nova string, o V8 cria um pequeno objeto que aponta para as duas strings.
(forma do objeto) Informações sobre objetos, como o número de propriedades que eles têm e uma referência a seus protótipos, que o V8 mantém internamente quando os objetos são criados e atualizados. Isso permite que o V8 represente de forma eficiente 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 string fatiado em vez de copiar todos os caracteres relevantes da string original. Esse novo objeto contém um ponteiro para a cadeia de caracteres original e descreve o intervalo de caracteres da cadeia de caracteres original a ser usado.
(Sistema) Vários objetos internos que ainda não foram categorizados de maneira mais significativa.
{foo, bar, baz} Objetos JavaScript simples categorizados por interface (lista de propriedades), entre chaves. Objetos JavaScript simples não são listados em uma categoria chamada Object, mas são representados por nomes e categorias baseados nas propriedades que o objeto contém, como {foo, bar, baz}.
InternalNode Objetos alocados fora do V8, como objetos C++ definidos pelo Blink, o mecanismo de renderização do Microsoft Edge.
sistema/Contexto 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 possa acessar essas variáveis.

Exibição de comparação

Para localizar objetos vazados, compare vários instantâneos entre si. Em um aplicativo da web, geralmente, fazer uma ação e, em seguida, a ação reversa não deve levar a mais objetos na memória. Por exemplo, ao abrir um documento e depois fechá-lo, o número de objetos na memória deve ser o mesmo de antes de abrir o documento.

Para verificar se determinadas operações não criam vazamentos:

  1. Tire um snapshot de heap antes de executar uma operação.

  2. Execute a operação. Ou seja, interaja com a página de alguma forma que possa estar causando um vazamento.

  3. Execute a operação inversa. Ou seja, faça a interação oposta e repita algumas vezes.

  4. Tire um segundo snapshot de heap.

  5. No segundo snapshot de heap, altere a exibição para Comparison, comparando-a com o Snapshot 1.

Na Exibição de comparação , a diferença entre dois instantâneos é exibida:

Exibição de comparação

Ao expandir um construtor na lista, são mostradas as instâncias de objeto adicionadas e excluídas.

Modo de exibição de contenção

A exibição Contenção permite que você espie os fechamentos de função, observe os objetos internos da máquina virtual (VM) que compõem seus objetos JavaScript e entenda quanta memória seu aplicativo usa em um nível muito baixo:

Modo de exibição de contenção

A exibição de contenção mostra os seguintes tipos de objetos:

Pontos de entrada da exibição de contenção Descrição
Objetos DOMWindow Objetos globais para código JavaScript.
Raízes de GC As raízes de GC usadas pelo coletor de lixo da máquina virtual JavaScript. As raízes de GC são compostas por mapas de objetos internos, tabelas de símbolos, pilhas de threads 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 Responsáveis pela retenção é atualizada quando você seleciona um objeto diferente na exibição Resumo, Contenção ou Comparação .

Na captura de tela a seguir, um objeto string foi selecionado na exibição Summary e a seção Retainers mostra que a string é retida pela x propriedade de uma instância da Item classe, encontrada no example-03.js arquivo:

A seção Retentores

Ocultar ciclos

Na seção Retentores , quando você analisa os objetos que retêm o objeto selecionado, você pode encontrar ciclos. Os ciclos ocorrem quando o mesmo objeto aparece mais de uma vez no caminho de retenção do objeto selecionado. Na seção Retentores , um objeto reciclado é indicado como acinzentado.

Para ajudar a simplificar o caminho do responsável pela retenção

O menu suspenso Filtrar bordas na seção Responsáveis de retenção,

Ocultar nós internos

Os nós internos são objetos específicos do V8 (o mecanismo JavaScript no Microsoft Edge).

Para ocultar nós internos na seção Responsáveis , no menu suspenso Filtrar bordas , selecione Ocultar interno.

Filtrar instantâneos de heap por tipos de nó

Use filtros para se concentrar em partes específicas de um snapshot de heap. Ao examinar todos os objetos em um snapshot de heap na ferramenta Memory, pode ser difícil se concentrar em objetos específicos ou caminhos de retenção.

Para focar 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 os objetos de cadeia de caracteres no snapshot de heap:

  1. Para abrir o filtro Tipos de Nó , clique em Padrão no canto superior direito.

  2. Selecione as entradas Matriz e Cadeia de caracteres.

    O snapshot de heap é atualizado para mostrar apenas os objetos array e string:

    Tipos de nó em um snapshot de heap na ferramenta Memória

Localizar um objeto específico

Para localizar um objeto no heap coletado, você pode pesquisar usando Ctrl+F e fornecer a ID do objeto.

Descobrir vazamentos de 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 ocorrem devido a nós DOM esquecidos e desanexados que permanecem na memória.

Para elementos desanexados, consulte também Localizar vazamentos de memória da árvore DOM (tipo > de criação de perfil "Heap snapshot" Desanexado), abaixo.

Considere a seguinte árvore DOM:

Subárvores DOM

A amostra 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");

Na seguinte amostra de código, 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 como lixo 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 como lixo 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 elemento pode ser coletado <div id="tree"> como lixo. Ambos treeRef e leafRef devem primeiro ser anulados, para que toda a árvore DOM sob o <div id="tree"> elemento seja coletada como lixo.

Página da Web de demonstração: Exemplo 6: vazamento de nós DOM

Para entender onde os nós DOM podem vazar e como detectar esse vazamento, abra a página da Web de exemplo Exemplo 6: vazamento de nós DOM em uma nova janela ou guia.

Página da Web de demonstração: Exemplo 8: Registrando alocações de heap

Abra a página da Web de exemplo Exemplo 8: Registrando alocações de heap em uma nova janela ou guia.

Página da Web de demonstração: Exemplo 9: vazamentos de DOM maiores que o esperado

Para ver por que um vazamento de DOM pode ser maior do que o esperado, abra a página da Web de exemplo Exemplo 9: vazamento de DOM maior do que o esperado em uma nova janela ou guia.

Analise o impacto dos fechamentos na memória

Para analisar o impacto dos fechamentos na memória, experimente este exemplo:

  1. Abra a página da Web da demonstração Eval is evil em uma nova janela ou guia.

  2. Registre um snapshot de heap.

  3. Na página da Web renderizada, clique no botão Closures with aval .

  4. Grave um segundo snapshot de heap.

    Na barra lateral, o número abaixo do segundo snapshot deve ser maior do que o número abaixo do primeiro snapshot. Isso indica que mais memória está sendo usada pela página da Web depois de clicar no botão Closures with aval .

  5. No segundo snapshot de heap, altere a exibição para Comparison e compare o segundo snapshot de heap com o primeiro snapshot de heap.

    O modo de exibição Comparação mostra que novas cadeias de caracteres foram criadas no segundo snapshot de heap:

    O Modo de Exibição de Comparação, mostrando que novas cadeias de caracteres foram criadas no segundo snapshot

  6. No modo de exibição Comparação, expanda o construtor (string).

  7. Clique na primeira entrada (cadeia de caracteres ).

    A seção Responsáveis por Retentores é atualizada e mostra que a largeStr variável mantém a cadeia de caracteres selecionada no modo de exibição de Comparação .

    A largeStr entrada é expandida automaticamente e mostra que a variável é retida eC pela função, que é o fechamento onde a variável é definida:

    A seção Retainers, mostrando que a cadeia de caracteres é retida pela função eC

Dica: Funções de nome para diferenciar entre fechamentos em um snapshot

Para distinguir facilmente entre os fechamentos do JavaScript em um snapshot de heap, forneça nomes às 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 snapshot do heap:

function createLargeClosure() {
    const largeStr = 'x'.repeat(1000000).toLowerCase();

    // This function is named.
    const lC = function lC() {
        return largeStr;
    };

    return lC;
}

Salvar e exportar strings de um snapshot de heap para JSON

Ao tirar um snapshot de heap na ferramenta Memory, você pode exportar todos os objetos string do snapshot para um arquivo JSON. Na ferramenta Memória , na seção Construtor , clique no botão Salvar tudo no arquivo ao lado da (string) entrada:

Salvar todas as cadeias de caracteres de um snapshot de heap em JSON

A ferramenta Memória exporta um arquivo JSON que contém todos os objetos de cadeia de caracteres do snapshot de heap:

Cadeias de caracteres do snapshot do heap, no arquivo JSON

Localizar vazamentos de memória da árvore DOM (tipo > de criação de perfil "Heap snapshot" Desanexado)

Uma maneira de localizar e exibir todos os elementos desanexados em uma página da Web é usar o tipo de criação de perfil Heap snapshot da ferramenta Memória e, em seguida, digitar Desanexado na caixa de texto Filtrar por classe, da seguinte maneira. Consulte também Ferramentas para investigar elementos desanexados em Corrigir problemas de memória.

O código a seguir produz nós DOM desanexados:

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

Esse código cria um ul nó com dez li filhos. Os nós são referenciados pelo código, mas não existem na árvore DOM, portanto, cada nó é desanexado.

Os instantâneos de heap são uma maneira de identificar nós desanexados. Um snapshot de heap mostra como a memória é distribuída entre os objetos JS e nós DOM para sua página no momento do snapshot.

Use o tipo de criação de perfil "Heap snapshot" para localizar elementos desanexados

Para usar o tipo de criação de perfil de snapshot Heap para localizar elementos desanexados:

  1. Abra uma página da Web, como a página da Web de demonstração de Elementos Desanexados, em uma nova janela ou guia.

  2. 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).

    O DevTools é aberto.

  3. No DevTools, na Barra de Atividades, selecione a ferramenta Memória (ícone da ferramenta Memória).

    Se essa guia não estiver visível, clique no botão Mais Ferramentas (ícone Mais Ferramentas) e selecione Memória. A ferramenta Memória é aberta:

    Abra a ferramenta Memória

    Se o botão de opção de snapshot de heap não for mostrado, porque um perfil já foi exibido, no canto superior esquerdo, clique em Perfis (o ícone Perfis).

    Você não precisa selecionar o botão de opção Heap snapshot neste ponto, porque a página da Web ainda não gerou nenhum elemento desanexado.

    Gere mensagens, que serão armazenadas pela instância JavaScript da classe Room:

  4. Na página da demonstração, clique no botão Tráfego rápido .

    A página da web de demonstração começa a gerar mensagens e exibi-las na página da web:

    Gerando algumas mensagens na página da Web de demonstração

  5. Depois que algumas mensagens forem exibidas, clique no botão Parar na página da Web de demonstração.

    Cada mensagem é um <div class="message"> elemento referenciado pela instância da sala 1 da Room classe. Não há elementos separados na árvore DOM da página da Web, porque todos os elementos da mensagem estão anexados à instância presente, Room 1, da classe Room .

    Mude para uma instância diferente da classe Room, para que os elementos sejam desanexados:

  6. Na página da Web de demonstração, clique no botão Room 2 , que corresponde a outra instância da Room classe.

    Na página da Web, as mensagens desaparecem:

    Vista inicial da sala 2

    As mensagens que foram geradas para a instância da sala 1 da classe Room (<div class="message"> elementos) não estão mais anexadas ao DOM, mas ainda são referenciadas pela instância da sala 1 da classe Room . São elementos separados, que podem causar vazamentos de memória, a menos que sejam usados novamente pela página da web.

    Obtenha a lista de elementos separados:

  7. No DevTools, na ferramenta Memória , clique no ícone Coletar lixo (o ícone 'Coletar lixo'):

    Obtendo um snapshot de heap

    O navegador executa a coleta de lixo, removendo todos os nós que não são mais referenciados por um objeto JavaScript.

  8. Na ferramenta Memória, selecione o botão de opção Heap snapshot.

  9. Clique no botão Fazer snapshot na parte inferior da ferramenta Memória.

    O snapshot é processado, carregado e, em seguida, listado na barra lateral Perfis, na seção Snapshots de heap.

  10. Na caixa de texto Filtrar por classe , digite detached:

    Filtrando nós desanexados e expandindo um nó desanexado

    Os elementos DOM desanexados que não podem ser coletados como lixo são exibidos.

    Identifique o código JavaScript que faz referência a um elemento separado específico:

  11. No snapshot do heap, expanda um objeto Desanexado, como Desanexado <div>, e selecione um Detached <div class="message"> nó.

    As informações são exibidas no painel Retentores na parte inferior da ferramenta Memória .

  12. No painel Retentores , clique no room.js:13 link para um item desmontado no Quarto em Matriz. A ferramenta Fontes é aberta, exibindo room.js, rolada para a linha 13:

    O código-fonte JavaScript na ferramenta Fontes

  13. Para inspecionar o possível vazamento de memória, estude o código que usa o unmounted array e certifique-se de que a referência ao nó seja removida quando não for mais necessária.

  14. Para retornar à ferramenta Memória , na Barra de endereços, selecione a ferramenta Memória .

Para obter maneiras adicionais de ver elementos desanexados, consulte Ferramentas para investigar elementos desanexados em Corrigir problemas de memória.

Confira também

Externo:

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 Creative Commons Atribuição 4.0 Internacional. A página original é encontrada aqui e é de autoria de Meggin Kearney.

Licença Creative Commons Este trabalho está licenciado sob uma Licença Creative Commons Atribuição 4.0 Internacional.