Partilhar via


Registar instantâneos de área dinâmica para dados com a ferramenta memória (tipo de criação de perfis "Heap snapshot")

Utilize o gerador de perfis de área dinâmica para dados na ferramenta Memória para fazer o seguinte:

  • Registe instantâneos de área dinâmica para dados JavaScript (área dinâmica para dados JS).
  • Analisar gráficos de memória.
  • Comparar instantâneos.
  • Localizar fugas de memória.

O gerador de perfis de área dinâmica para dados DevTools mostra a distribuição de memória utilizada pelos objetos JavaScript e por nós DOM relacionados na página Web composta.

Faça um snapshot

  1. Abra a página Web que pretende analisar. Por exemplo, abra a página de demonstração Objetos dispersos numa nova janela ou separador.

  2. Para abrir o DevTools, clique com o botão direito do rato na página Web e, em seguida, selecione Inspecionar. Em alternativa, prima Ctrl+Shift+I (Windows, Linux) ou Comando+Opção+I (macOS). O DevTools é aberto.

  3. Em DevTools, na Barra de Atividade, selecione o separador Memória . Se esse separador não estiver visível, clique no botão Mais ferramentas (ícone Mais ferramentas).

  4. Na secção Selecionar tipo de criação de perfis, selecione o botão de opção Snapshot área dinâmica para dados.

  5. Em Selecionar instância de VM JavaScript, selecione a VM JavaScript que pretende criar.

  6. Clique no botão Tirar snapshot:

A ferramenta Memória, a opção snapshot área dinâmica para dados está selecionada e o botão Tomar snapshot está realçado

Depois de a área dinâmica para dados recentemente gravada snapshot ter sido carregada para DevTools e ter sido analisada, a snapshot é apresentada e é apresentada uma nova entrada na barra lateral Perfis em Instantâneos da Área Dinâmica para Dados:

Tamanho total dos objetos acessí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 na área dinâmica para dados snapshot, veja Object sizes and distances in Memory terminlogy (Tamanhos e distâncias de objetos na terminologia da memória).

O snapshot apenas apresenta os objetos do grafo de memória que estão acessíveis a partir do objeto global. Tirar um snapshot começa sempre com uma libertação da memória.

Faça outra snapshot

Para efetuar outra snapshot quando uma já for apresentada 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

Ver instantâneos

Os instantâneos de área dinâmica para dados podem ser visualizados de várias formas diferentes na ferramenta Memória . Cada forma de visualizar uma área dinâmica para dados snapshot na IU 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 utilizam, com base em tipos agrupados por nome de construtor. Útil para localizar fugas de DOM.
Comparação Apresenta as diferenças entre dois instantâneos. Comparar dois (ou mais) instantâneos de memória de antes e depois de uma operação. Inspecionar o delta na memória libertada e inspecionar a contagem de referências ajuda-o a confirmar a presença e a causa de uma fuga de memória e ajuda a determinar a causa.
Contenção Permite a exploração de conteúdos de área dinâmica para dados. Fornece uma melhor vista da estrutura de objetos, ajudando a analisar objetos referenciados no espaço de nomes global (janela) para descobrir o que está a manter os objetos por perto. Utilize-o para analisar fechos e explorar os objetos a um nível baixo.

Para alternar entre vistas, utilize a lista pendente na parte superior da ferramenta Memória :

Alternar seletor de vistas

Itens omitidos de instantâneos de área dinâmica para dados

As propriedades implementadas com getters que executam código nativo não são capturadas na área dinâmica para dados snapshot, porque essas propriedades não são armazenadas na área dinâmica para dados javaScript.

Os valores que não sejam de cadeia, como números, não são capturados.

Exibição resumida

A vista Resumo nas listas da ferramenta Memória :

  • Grupos de construtores de objetos.
  • Nomes de categorias especiais, como (matriz), (código compilado) ou uma lista de propriedades como {foo, bar, baz}.

Inicialmente, é aberta uma área dinâmica para dados snapshot na vista Resumo, que apresenta uma lista de construtores:

Exibição resumida

Cada construtor na lista pode ser expandido para mostrar os objetos que foram instanciados com esse construtor.

Para cada construtor na lista, a vista Resumo também mostra um número, como ×123, que indica o número total de objetos criados com o construtor. A vista Resumo também mostra as seguintes colunas:

Nome da coluna Descrição
Distância Apresenta a distância até à raiz com o caminho mais curto e simples dos nós. Veja Terminologia dadistância na memória.
Tamanho raso Apresenta a soma de tamanhos rasos de todos os objetos criados por uma determinada função de construtor. O tamanho raso é o tamanho da área dinâmica para dados JavaScript que é mantida diretamente por um objeto. O tamanho raso de um objeto é geralmente pequeno, porque um objeto JavaScript armazena frequentemente apenas a descrição do objeto, não os valores, na memória direta do objeto. A maioria dos objetos JavaScript armazena os respetivos valores num arquivo de apoio que está noutro local na área dinâmica para dados javaScript e expõe apenas um pequeno objeto de wrapper na parte da área dinâmica para dados JavaScript que pertence diretamente ao objeto. Veja Tamanho raso na terminologia da memória.
Tamanho retido Apresenta o tamanho máximo retido entre o mesmo conjunto de objetos. O tamanho da memória que pode libertar depois de um objeto ser eliminado (e os dependentes deixarem de estar acessíveis) é denominado tamanho retido. Veja Tamanho retido na terminologia da memória.

Depois de expandir um construtor na vista Resumo , todas as instâncias do construtor são apresentadas. Para cada instância, os tamanhos rasos e retidos são apresentados nas colunas correspondentes. O número após o @ caráter é o ID exclusivo do objeto, o que lhe permite comparar instantâneos de área dinâmica para dados por objeto.

Entradas de construtor

A vista Resumo na ferramenta Memória lista os grupos de construtores de objetos:

Grupos de construtores

Os grupos de construtores na vista Resumo podem ser funções incorporadas, como Array ou Object, ou podem ser funções definidas no 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 vista Resumo na ferramenta Memória inclui os seguintes nomes de categorias especiais, que não se baseiam em construtores. A maioria destes nomes de categoria são apresentados entre parênteses.

Nome da categoria Descrição
(matriz) Vários objetos internos semelhantes a matrizes que não correspondem diretamente a objetos visíveis a partir de JavaScript, como o conteúdo de matrizes JavaScript ou as propriedades nomeadas dos objetos JavaScript.
(código compilado) Dados internos de que o V8 (motor JavaScript do Microsoft Edge) precisa para executar funções definidas por JavaScript ou WebAssembly. O V8 gere automaticamente a utilização da memória nesta categoria: se uma função for executada muitas vezes, o V8 utiliza 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, a V8 poderá eliminar os dados internos dessa função.
(cadeia concatenada) Quando duas cadeias são concatenadas em conjunto, como quando utiliza o operador JavaScript + , o V8 pode optar por representar o resultado internamente como uma cadeia concatenada. Em vez de copiar todos os carateres das duas cadeias para uma nova cadeia, v8 cria um objeto pequeno que aponta para as duas cadeias.
(forma de objeto) Informações sobre objetos, como o número de propriedades que têm e uma referência aos respetivos protótipos, que o V8 mantém internamente quando os objetos são criados e atualizados. Isto permite que o V8 represente objetos com as mesmas propriedades de forma eficiente.
(cadeia segmentada) Ao criar uma subcadeia, como quando utiliza o método JavaScript substring , o V8 pode optar por criar um objeto de cadeia segmentada em vez de copiar todos os carateres relevantes da cadeia original. Este novo objeto contém um ponteiro para a cadeia original e descreve o intervalo de carateres da cadeia original a utilizar.
(sistema) Vários objetos internos que ainda não foram categorizados de forma mais significativa.
{foo, bar, baz} Objetos JavaScript simples categorizados por interface (lista de propriedades), em chavetas. Os objetos JavaScript simples não estão listados numa categoria denominada Objeto, mas são representados por nomes e categorias que se baseiam nas propriedades que o objeto contém, como {foo, bar, baz}.
InternalNode Objetos alocados fora do V8, como objetos C++ definidos pelo Blink, o motor de composição do Microsoft Edge.
sistema/Contexto Variáveis locais de um âmbito JavaScript que podem ser acedidas por alguma função aninhada. Cada instância de função contém um ponteiro interno para o contexto em que é executada, para que possa aceder a essas variáveis.

Vista de comparação

Para localizar objetos vazados, compare vários instantâneos entre si. Normalmente, numa aplicação Web, efetuar 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, em seguida, 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 fugas:

  1. Faça uma área dinâmica para dados snapshot antes de executar uma operação.

  2. Executar a operação. Ou seja, interaja com a página de alguma forma que possa estar a causar uma fuga.

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

  4. Tome uma segunda área dinâmica para snapshot.

  5. Na segunda área dinâmica para dados snapshot, altere a vista para Comparação, comparando-a com o Instantâneo 1.

Na vista Comparação , é apresentada a diferença entre dois instantâneos:

Vista de comparação

Ao expandir um construtor na lista, são apresentadas as instâncias de objetos adicionados e eliminados.

Vista de contenção

A vista Contenção permite-lhe pré-visualizar os encerramentos de funções, observar objetos internos de máquina virtual (VM) que compõem os objetos JavaScript e compreender a quantidade de memória que a sua aplicação utiliza a um nível muito baixo:

Vista de contenção

A vista Contenção mostra os seguintes tipos de objetos:

Pontos de entrada da vista de contenção Descrição
Objetos DOMWindow Objetos globais para código JavaScript.
Raízes GC As raízes GC utilizadas pelo recoletor de lixo da máquina virtual JavaScript. As raízes GC são compostas por mapas de objetos incorporados, tabelas de símbolos, pilhas de threads de VM, caches de compilação, âmbitos de identificador e identificadores globais.
Objetos nativos Objetos criados pelo browser, como nós DOM e regras CSS, que são apresentados na máquina virtual JavaScript para permitir a automatização.

A secção Retentores

A secção Retentores é apresentada na parte inferior da ferramenta Memória e mostra todos os objetos que apontam para o objeto selecionado. A secção Retentores é atualizada quando seleciona um objeto diferente na vista Resumo, Contenção ou Comparação .

Na captura de ecrã seguinte, foi selecionado um objeto de cadeia de carateres na vista Resumo e a secção Retentores mostra que a cadeia é mantida pela x propriedade de uma instância da Item classe, encontrada no example-03.js ficheiro:

A secção Retentores

Ocultar ciclos

Na secção Retentores , ao analisar os objetos que retêm o objeto selecionado, poderá encontrar ciclos. Os ciclos ocorrem quando o mesmo objeto aparece mais do que uma vez no caminho de retenção do objeto selecionado. Na secção Retentores , um objeto ciclod é indicado por estar desativado.

Para ajudar a simplificar o caminho de retenção, oculte os ciclos na secção Retentores ao clicar no menu pendente Filtrar arestas e, em seguida, selecionar Ocultar ciclo:

O menu pendente Filtrar arestas na secção Retentores,

Ocultar nós internos

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

Para ocultar nós internos da secção Retentores , no menu pendente Filtrar arestas , selecione Ocultar interno.

Filtrar instantâneos de área dinâmica para dados por tipos de nós

Utilize filtros para se concentrar em partes específicas de uma área dinâmica para dados snapshot. Ao observar todos os objetos numa área dinâmica para dados snapshot na ferramenta Memória, pode ser difícil concentrar-se em objetos específicos ou manter caminhos.

Para se concentrar apenas em tipos específicos de nós, utilize o filtro Tipos de Nó , no canto superior direito. Por exemplo, para ver apenas as matrizes e objetos de cadeia na área dinâmica para dados snapshot:

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

  2. Selecione as entradas Matriz e Cadeia .

    A área dinâmica para dados snapshot é atualizada para mostrar apenas os objetos de matriz e cadeia:

    Tipos de Nós numa área dinâmica para dados snapshot na ferramenta Memória

Localizar um objeto específico

Para localizar um objeto na área dinâmica para dados recolhida, pode procurar com Ctrl+F e atribuir o ID do objeto.

Descobrir fugas do DOM

A ferramenta Memória tem a capacidade de mostrar as dependências bidirecionais que, por vezes, existem entre objetos nativos do browser (nós DOM, regras CSS) e objetos JavaScript. Isto ajuda a detetar fugas de memória que ocorrem devido a nós DOM esquecidos e desanexados que permanecem na memória.

Para obter elementos desanexados, veja também Localizar fugas de memória de árvore DOM (tipo > de criação de perfis "Área dinâmica para dados snapshot" Desanexada), abaixo.

Considere a seguinte árvore DOM:

Subárvores DOM

O exemplo de código seguinte cria as variáveis treeRef javaScript e leafRef, que referenciam 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 seguinte exemplo 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 recolhido da memória porque a variável treeRef JavaScript ainda existe. A treeRef variável referencia diretamente o <div id="tree"> elemento . No seguinte exemplo de código, a treeRef variável é nula:

// Remove the treeRef variable.
treeRef = null;

O <div id="tree"> elemento ainda não pode ser recolhido da memória porque a variável leafRef JavaScript ainda existe. A leafRef.parentNode propriedade referencia o <div id="tree"> elemento . No seguinte exemplo de código, a leafRef variável é nula:

// Remove the leafRef variable.
leafRef = null;

Neste momento, o <div id="tree"> elemento pode ser recolhido da memória. Tanto como treeRefleafRef têm de ser anulados, para que toda a árvore DOM sob o <div id="tree"> elemento seja recolhida na memória.

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

Para compreender onde é que os nós DOM podem vazar e como detetar tais fugas, abra a página Web de exemplo Exemplo 6: Fuga de nós DOM numa nova janela ou separador.

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

Para ver por que motivo uma fuga de DOM pode ser maior do que o esperado, abra a página Web de exemplo Exemplo 9: Fugas de DOM maiores do que o esperado numa nova janela ou separador.

Analisar o impacto dos encerramentos na memória

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

  1. Abrir a página Web de demonstração É numa nova janela ou separador.

  2. Grave uma área dinâmica para dados snapshot.

  3. Na página Web composta, clique no botão Fechos com valor .

  4. Grave uma segunda área dinâmica para dados snapshot.

    Na barra lateral, o número abaixo da segunda snapshot deve ser maior do que o número abaixo do primeiro snapshot. Isto indica que está a ser utilizada mais memória pela página Web depois de clicar no botão Encerramentos com valor .

  5. Na segunda área dinâmica para dados snapshot, altere a vista para Comparação e, em seguida, compare a segunda área dinâmica para dados snapshot com a primeira área dinâmica para dados snapshot.

    A vista Comparação mostra que foram criadas novas cadeias na segunda área dinâmica para dados snapshot:

    A vista Comparação, que mostra que foram criadas novas cadeias na segunda snapshot

  6. Na vista Comparação , expanda o construtor (cadeia ).

  7. Clique na primeira entrada (cadeia ).

    A secção Retentores é atualizada e mostra que a largeStr variável retém a cadeia selecionada na vista Comparação .

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

    A secção Retentores, que mostra que a cadeia de carateres é mantida pela função eC

Sugestão: atribua um nome às funções para diferenciar entre fechos num snapshot

Para distinguir facilmente entre fechos de JavaScript numa área dinâmica para dados snapshot, atribua nomes às suas funções.

O exemplo seguinte utiliza uma função sem nome para devolver 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 seguinte dá o nome à função, o que facilita a distinção entre fechos na área dinâmica para dados snapshot:

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

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

    return lC;
}

Guardar e exportar cadeias de carateres de uma área dinâmica para dados snapshot para JSON

Ao utilizar uma área dinâmica para dados snapshot na ferramenta Memória, pode exportar todos os objetos de cadeia do snapshot para um ficheiro JSON. Na ferramenta Memória , na secção Construtor , clique no botão Guardar tudo no ficheiro junto à (string) entrada:

Guardar todas as cadeias de dados de uma área dinâmica para dados snapshot em JSON

A ferramenta Memória exporta um ficheiro JSON que contém todos os objetos de cadeia da área dinâmica para dados snapshot:

Cadeias da área dinâmica para dados snapshot, no ficheiro JSON

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

Uma forma de localizar e apresentar todos os elementos desanexados numa página Web é utilizar o tipo de criação de dados snapshot da ferramenta memória e, em seguida, escrever Desencaixado na caixa de texto Filtrar por classe, da seguinte forma. Veja também Ferramentas para investigar elementos desanexados em Corrigir problemas de memória.

O código seguinte 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);

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

Os instantâneos de área dinâmica para dados são uma forma de identificar nós separados. Uma área dinâmica para dados snapshot mostra como a memória é distribuída entre os objetos JS e os nós DOM da sua página no momento da snapshot.

Utilize o tipo de criação de perfis "Heap snapshot" para localizar elementos desanexados

Para utilizar o tipo de criação de perfis da Área Dinâmica para Dados snapshot para localizar elementos desanexados:

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

  2. Clique com o botão direito do rato na página Web e, em seguida, selecione Inspecionar. Em alternativa, prima Ctrl+Shift+I (Windows, Linux) ou Comando+Opção+I (macOS).

    O DevTools é aberto.

  3. Em DevTools, na Barra de Atividade, selecione a ferramenta Memória (ícone da ferramenta memória).

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

    Abrir a ferramenta Memória

    Se o botão de opção Snapshot Área Dinâmica para Dados não for apresentado, porque já é apresentado um perfil, no canto superior esquerdo, clique em Perfis (o ícone Perfis).

    Não precisa de selecionar o botão de opção Snapshot Área Dinâmica para Dados neste momento, porque a página Web ainda não gerou elementos desanexados.

    Gerar mensagens, que serão armazenadas pela instância javaScript da classe Room:

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

    A página Web de demonstração começa a gerar mensagens e a apresentá-las na página Web:

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

  5. Depois de algumas mensagens serem apresentadas, clique no botão Parar na página Web de demonstração.

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

    Mude para uma instância diferente da classe Sala, para que os elementos se desanexem:

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

    Na página Web, as mensagens desaparecem:

    Vista inicial da Sala 2

    As mensagens que foram geradas para a instância da Sala 1 da classe Sala (<div class="message"> elementos) já não estão anexadas ao DOM, mas continuam a ser referenciadas pela instância da Sala 1 da classe Sala . São elementos desanexados, o que pode causar fugas de memória, a menos que sejam novamente utilizados pela página Web.

    Obtenha a lista de elementos desanexados:

  7. Em DevTools, na ferramenta Memória , clique no ícone Recolher lixo (o ícone ):

    Tomar uma área dinâmica para dados snapshot

    O browser executa a libertação da memória, removendo os nós que já não são referenciados por um objeto JavaScript.

  8. Na ferramenta Memória, selecione o botão de opção Snapshot área dinâmica para dados.

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

    O snapshot é processado, carregado e, em seguida, listado na barra lateral Perfis, na secção Instantâneos da área dinâmica para dados.

  10. Na caixa de texto Filtrar por classe , escreva desanexado:

    Filtrar por nós desanexados e expandir um nó desanexado

    São apresentados os elementos do DOM desanexados que não podem ser recolhidos da memória.

    Identifique o código JavaScript que referencia um elemento desanexado específico:

  11. Na área dinâmica para dados snapshot, expanda um objeto Desanexado, como Desanexar <div>, e, em seguida, selecione um nó Detached <div class="message">.

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

  12. No painel Retentores , clique na room.js:13 ligação para um item de Sala desmontado emMatriz. A ferramenta Origens é aberta, apresentando room.js, desloque-se para a linha 13:

    O código fonte javaScript na ferramenta Origens

  13. Para inspecionar a possível fuga de memória, analise o código que utiliza a unmounted matriz e certifique-se de que a referência ao nó é removida quando já não for necessária.

  14. Para regressar à ferramenta Memória , na Barra de Endereço, selecione a ferramenta Memória .

Para obter formas adicionais de ver elementos desanexados, veja 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 partilhado pela Google e utilizado de acordo com os termos descritos na Licença Internacional Creative Commons Attribution 4.0. A página original é encontrada aqui e é da autoria de Meggin Kearney.

Licença Creative Commons Este trabalho é licenciado ao abrigo de uma Licença Internacional creative Commons Attribution 4.0.