Monitorando toda a memória usada por uma página da Web: performance.measureMemory ()

O autor do artigo, cuja tradução publicamos hoje, fala sobre como monitorar a memória alocada nas páginas da web. A atenção cuidadosa à memória das páginas que trabalham na produção ajuda a manter a produtividade dos projetos da Web em alto nível.



Os navegadores controlam automaticamente a memória alocada nas páginas da web. Quando uma página cria um objeto, o navegador, usando seus mecanismos internos, aloca memória para armazenar esse objeto. Como a memória não é um recurso infinito, o navegador executa periodicamente a coleta de lixo, durante a qual objetos desnecessários são detectados e a memória que eles ocupam é limpa. O processo de detecção de tais objetos, no entanto, não é ideal. Foi provadoque a identificação absolutamente precisa e completa de tais objetos é uma tarefa insolúvel. Como resultado, os navegadores estão substituindo a idéia de encontrar "objetos desnecessários" pela idéia de encontrar "objetos inacessíveis". Se uma página da Web não puder acessar o objeto através de suas variáveis ​​e campos de outros objetos acessíveis, isso significa que o navegador pode limpar com segurança a memória ocupada por esse objeto. A diferença entre "desnecessário" e "inacessível" leva a vazamentos de memória, conforme ilustrado no exemplo a seguir:

const object = { a: new Array(1000), b: new Array(2000) };
setInterval(() => console.log(object.a), 1000);

Há uma grande variedade desnecessária aqui b, mas o navegador não libera a memória que ocupa devido ao fato de ser alcançável através da propriedade do objeto object.bno retorno de chamada. Como resultado, a memória ocupada por esta matriz está vazando.

Vazamentos de memória são uma ocorrência comum no desenvolvimento da web. Eles aparecem com facilidade nos programas quando, por exemplo, os desenvolvedores esquecem de cancelar a inscrição no ouvinte de eventos, quando capturam acidentalmente objetos em um elemento iframe, quando esquecem de fechar o trabalhador, quando coletam objetos em matrizes. Se uma página da Web tiver vazamentos de memória, isso levará ao fato de que, com o tempo, o consumo de memória da página aumenta. Essa página parece lenta e lenta para os usuários.

O primeiro passo para resolver este problema é fazer medições. A nova API performance.measureMemory () permite que os desenvolvedores medam o uso de memória pelas páginas da Web em produção e, como resultado, detectam vazamentos de memória que passam despercebidos nos testes locais.

Qual a diferença entre a nova API performance.measureMemory () e a antiga performance.memory?


Se você estiver familiarizado com a API não padrão existente performance.memory, poderá estar interessado na questão de como a nova API difere da antiga. A principal diferença é que a API antiga retorna o tamanho do heap JavaScript e a nova avalia o uso de memória de toda a página da web. Essa distinção é importante quando o Chrome organiza o compartilhamento de heap entre várias páginas da web (ou várias instâncias da mesma página). Nesses casos, os resultados retornados pela API antiga podem ficar distorcidos. Como a API antiga é definida em termos específicos da implementação, como um heap, padronizá-la é um negócio inútil.

Outra diferença é que, no Chrome, a nova API faz medições de memória ao coletar lixo. Isso reduz o “ruído” nos resultados da medição, mas pode levar algum tempo para obter os resultados. Observe que os criadores de outros navegadores podem decidir implementar a nova API sem vincular à coleta de lixo.

Maneiras recomendadas de usar a nova API


O uso da memória pelas páginas da Web depende da ocorrência de eventos, das ações do usuário e da coleta de lixo. É por isso que a API foi performance.measureMemory()projetada para estudar o nível de uso de memória na produção. Os resultados da chamada dessa API em um ambiente de teste são menos úteis. Aqui estão alguns exemplos de opções para usá-lo:

  • - .
  • A/B- , .
  • .
  • , . .


Atualmente, a API em questão é suportada apenas no Chrome 83, de acordo com o esquema de avaliação de origem. Os resultados retornados pela API são altamente dependentes da implementação, pois diferentes navegadores usam maneiras diferentes de representar objetos na memória e maneiras diferentes de avaliar o nível de uso da memória. Os navegadores podem excluir algumas áreas da memória da contabilidade se a contabilidade completa de toda a memória usada for uma tarefa excessivamente difícil ou impossível. Como resultado, podemos dizer que os resultados produzidos por essa API em diferentes navegadores não são comparáveis. Faz sentido comparar apenas os resultados obtidos no mesmo navegador.

Progresso atual do trabalho


Degraudoença
1. Criando explicações da API
Concluído
2. Criando um rascunho de especificação
Realizada
3. Obtenção de feedback e finalização do projeto
Realizada
4. Testes experimentais de origem
Realizada
5. Lançamento
Não foi iniciado

Usando performance.measureMemory ()


▍ Ativar suporte à avaliação de origem


A API performance.measureMemory()está disponível no Chrome 83 de acordo com o esquema de avaliação de origem. Espera-se que esta fase termine com o lançamento do Chrome 84. O

Trial de origem permite que os desenvolvedores aproveitem os novos recursos do Chrome e compartilhem seus comentários sobre a conveniência, a usabilidade e a eficácia desses recursos com a comunidade da web. Detalhes sobre este programa podem ser encontrados aqui . Você pode se inscrever no programa na página de registro.

▍Registro no programa Teste de Origem


  1. Solicite um token para a oportunidade em que você está interessado.
  2. Adicione o token às páginas do projeto piloto. Existem 2 maneiras de fazer isso:

    • Adicione uma <meta>tag origin-trialao título de cada página. Por exemplo, ele pode ter esta aparência: <meta http-equiv="origin-trial" content="TOKEN_GOES_HERE">.
    • Se você tiver acesso às configurações do servidor, ele poderá adicionar um token usando um cabeçalho HTTP Origin-Trial. Como resultado, o cabeçalho de resposta deve aparecer algo como o seguinte: Origin-Trial: TOKEN_GOES_HERE.

▍Ativando um novo recurso através dos sinalizadores do Chrome


A fim de experimentar performance.measureMemory(), enquanto dispensando com o token de Origem Julgamento, você precisa habilitar a bandeira #experimental-web-platform-featuresno chrome://flags.

HecVerificação de uso da API


Uma chamada de função performance.measureMemory()pode falhar, com um SecurityError lançado . Isso pode acontecer se o ambiente não atender aos requisitos de segurança para vazamento de informações. Durante o teste de avaliação de origem no Chrome, essa API requer a inclusão do isolamento do site . Quando a API estiver pronta para uso normal, ela dependerá da propriedade crossOriginIsolated . Uma página da web pode operar nesse modo, definindo os cabeçalhos COOP e COEP .

Aqui está um código de exemplo:

if (performance.measureMemory) {
  let result;
  try {
    result = await performance.measureMemory();
  } catch (error) {
    if (error instanceof DOMException &&
        error.name === "SecurityError") {
      console.log("The context is not secure.");
    } else {
      throw error;
    }
  }
  console.log(result);
}

TestingTeste local


O Chrome faz uma medição de memória ao coletar lixo. Isso significa que o acesso à API não resolve instantaneamente a promessa. Para obter o resultado, você precisa aguardar a próxima sessão de coleta de lixo. A API inicia forçosamente a coleta de lixo após um certo tempo limite, atualmente definido como 20 segundos. Se você executar o Chrome com um sinalizador de linha de comando --enable-blink-features='ForceEagerMeasureMemory', o tempo limite será reduzido a zero, o que é útil para depuração local e teste local.

Exemplo


É recomendável usar a nova API definindo um monitor de memória global que mede o nível de uso de memória de toda a página e envie os resultados para o servidor, onde eles podem ser agregados e analisados. A maneira mais fácil de trabalhar com esta API é fazer medições periódicas. Por exemplo, eles podem executar a cada Mminuto. Isso, no entanto, introduz distorções nos dados, pois podem ocorrer picos no uso da memória entre as medições. O exemplo a seguir demonstra como, usando o processo de Poisson , fazer medições livres de erros sistemáticos. Essa abordagem garante que as sessões de medição possam, com igual probabilidade, ocorrer a qualquer momento ( aqui está uma demonstração dessa abordagem,aqui está o código fonte).

Primeiro, declare uma função que planeja o próximo início de uma sessão para medir a quantidade de memória consumida usando uma função setTimeout()com um intervalo definido aleatoriamente. Esta função deve ser chamada após carregar a página na janela do navegador.

function scheduleMeasurement() {
  if (!performance.measureMemory) {
    console.log("performance.measureMemory() is not available.");
    return;
  }
  const interval = measurementInterval();
  console.log("Scheduling memory measurement in " +
      Math.round(interval / 1000) + " seconds.");
  setTimeout(performMeasurement, interval);
}

//       .
window.onload = function () {
  scheduleMeasurement();
}

A função measurementInterval()encontra um intervalo aleatório, expresso em milissegundos, configurado de tal maneira que uma medição seja realizada aproximadamente a cada cinco minutos. Se você estiver interessado nos conceitos matemáticos nos quais essa função se baseia, leia sobre a distribuição exponencial .

function measurementInterval() {
  const MEAN_INTERVAL_IN_MS = 5 * 60 * 1000;
  return -Math.log(Math.random()) * MEAN_INTERVAL_IN_MS;
}

Como resultado, a função assíncrona performMeasurement()chama nossa API, registra o resultado e planeja a próxima medição.

async function performMeasurement() {
  // 1.  performance.measureMemory().
  let result;
  try {
    result = await performance.measureMemory();
  } catch (error) {
    if (error instanceof DOMException &&
        error.name === "SecurityError") {
      console.log("The context is not secure.");
      return;
    }
    //    .
    throw error;
  }
  // 2.  .
  console.log("Memory usage:", result);
  // 3.   .
  scheduleMeasurement();
}

Os resultados da medição podem ser assim:

// ,    :
{
  bytes: 60_000_000,
  breakdown: [
    {
      bytes: 40_000_000,
      attribution: ["https://foo.com"],
      userAgentSpecificTypes: ["Window", "JS"]
    },
    {
      bytes: 20_000_000,
      attribution: ["https://foo.com/iframe"],
      userAgentSpecificTypes: ["Window", "JS"]
    }
  ]
}

Uma estimativa do nível geral de uso de memória é exibida no campo bytes. Ao derivar essa estimativa, são utilizados os separadores dos dígitos dos números. Esses valores são altamente dependentes da implementação. Se eles forem recebidos por navegadores diferentes, você não poderá compará-los. A maneira como eles são obtidos pode variar mesmo em versões diferentes do mesmo navegador. Enquanto durar o programa Origin Trial, os valores retornados incluem indicadores de uso de memória JavaScript pela janela principal, indicadores de uso de memória de elementos iframedo mesmo site e indicadores de janelas relacionadas. Quando a API estiver pronta, esse valor representará informações sobre a memória consumida pelo JavaScript, o DOM, todos os elementos iframeassociados às janelas e aos trabalhadores da web.

Listabreakdownfornece informações mais detalhadas sobre a memória usada. Cada entrada descreve um pedaço de memória e associa esse fragmento a um conjunto de janelas, elementos iframeou trabalhadores identificados por uma URL. O campo userAgentSpecificTypeslista os tipos de memória determinados pelos recursos de implementação.

É importante considerar essas listas de uma maneira geral e não tentar, baseando-se nos recursos de um determinado navegador, analisar tudo com base nelas. Por exemplo, alguns navegadores podem retornar uma lista breakdownvazia ou campos vazios attribution. Outros navegadores podem retornar attributionvários URLs em um elemento , indicando que eles não podem identificar a qual desses URLs a memória pertence.

Comentários


O Grupo de comunidade de desempenho da Web e a equipe de desenvolvimento do Google Chrome ficarão felizes em descobrir o que você pensa performance.measureMemory()e aprender sobre sua experiência usando essa API.

Compartilhe suas idéias sobre o dispositivo API conosco


Existe algo nesta API que não funciona conforme o esperado? Talvez falte algo que você precisa para implementar sua ideia? Abra uma nova tarefa no rastreador de projeto ou comente uma tarefa existente.

Relatar um problema de implementação


Encontrou um erro na sua implementação do Chrome? Ou talvez a implementação seja diferente da especificação? Registre o erro aqui: new.crbug.com . Tente incluir o máximo de detalhes possível em sua mensagem, inclua instruções simples sobre como reproduzir o erro e indique que o problema está relacionado Blink>PerformanceAPIs. O Glitch é uma maneira muito boa de demonstrar erros .

Apoie-nos


performance.measureMemory()Você está planejando usar ? Se assim for, conte-nos sobre isso. Essas histórias ajudam a equipe de desenvolvimento do Chrome a priorizar. Essas histórias mostram aos criadores de outros navegadores a importância de oferecer suporte a novos recursos. Se desejar, envie um tweet para @ChromiumDev e informe-nos onde e como você usa a nova API.

Queridos leitores! Você já tentou performance.measureMemory()?


All Articles