Apresentação do Memory Inspector

Kim-Anh Tran
Kim-Anh Tran

Este artigo apresenta o Inspetor de memória que chegou ao Chrome 91. Com ele, é possível inspecionar o ArrayBuffer, o TypedArray, o DataView e a memória do Wasm.

Introdução

Você já quis entender os dados do ArrayBuffer? Antes do Inspetor de memória, o DevTools só permitia insights limitados sobre ArrayBuffers. A inspeção da visualização Escopo durante uma sessão de depuração era limitada à visualização de uma lista de valores únicos dentro do buffer da matriz, o que dificultava a compreensão dos dados como um todo. Por exemplo, a visualização Escopo mostra o buffer como intervalos expansíveis de matrizes no exemplo abaixo:

Visualização do escopo no DevTools

Navegar até um certo intervalo dentro do buffer era um aspecto problemático, exigindo que o usuário role para baixo para finalmente chegar ao índice. No entanto, mesmo que navegar até uma posição seja fácil, essa maneira de inspecting os valores é complicada: é difícil dizer o que esses números significam. E se eles não precisarem ser interpretados como bytes únicos, mas como números inteiros de 32 bits, por exemplo?

Como inspecionar valores usando o Inspetor de memória

Inspetor de memória

Com o Chrome 91, apresentamos o Inspetor de memória, uma ferramenta para inspecionar buffers de matriz. Talvez você já tenha visto ferramentas de inspeção de memória para visualizar dados binários, que mostram o conteúdo binário em uma grade junto com os endereços e oferecem maneiras diferentes de interpretar os valores. É isso que o Inspetor de memória está trazendo para você. Com o Inspetor de memória, agora é possível visualizar o conteúdo, navegar por ele e selecionar os tipos a serem usados para interpretar os valores em questão. Ele mostra os valores ASCII diretamente ao lado dos bytes e permite que o usuário selecione um endianness diferente. Confira o Memory Inspector em ação abaixo:

Quer fazer um teste? Para aprender a abrir o Memory Inspector e conferir o buffer de matriz (ou TypedArray, DataView ou Wasm Memory) e mais informações sobre como usá-lo, consulte nossa documentação sobre o Memory Inspector. Teste estes exemplos de brinquedos (para JS, Wasm e C++).

Como projetar o Inspetor de memória

Nesta parte, vamos analisar como o Inspetor de memória foi projetado usando componentes da Web e mostrar uma das metas de design que tínhamos e como a implementamos. Se tiver curiosidade e quiser ver mais, confira nosso documento de design do Inspetor de memória.

Talvez você tenha visto nossa postagem do blog sobre Migrar para componentes da Web, na qual Jack publicou nosso guia interno sobre como criar componentes de IU usando componentes da Web. A migração para Web Components coincide com nosso trabalho no Memory Inspector e, como resultado, decidimos experimentar o novo sistema. Confira abaixo um diagrama que mostra os componentes que criamos para criar o Inspetor de memória. Observe que o chamamos internamente de Inspetor de memória linear:

Componentes da Web

O componente LinearMemoryInspector é o pai que combina os subcomponentes que criam todos os elementos no Inspetor de memória. Basicamente, ela usa uma Uint8Array e uma address e, a cada mudança, propaga os dados para os filhos, o que aciona uma nova renderização. O próprio LinearMemoryInspector renderiza três subcomponentes:

  1. LinearMemoryViewer (mostrando os valores),
  2. LinearMemoryNavigator (permitindo a navegação)
  3. LinearMemoryValueInterpreter (mostra interpretações diferentes de tipo dos dados subjacentes).

O último é um componente pai, que renderiza a ValueInterpreterDisplay (mostrando os valores) e a ValueInterpreterSettings (selecionando quais tipos serão mostrados na tela).

Cada um dos componentes foi projetado para representar apenas um componente pequeno da interface, de modo que os componentes possam ser reutilizados, se necessário. Sempre que novos dados são definidos em um componente, uma nova renderização é acionada, mostrando a mudança refletida nos dados definidos no componente. Veja abaixo um exemplo de fluxo de trabalho com nossos componentes, em que o usuário altera o endereço na barra de endereço, o que aciona uma atualização configurando os novos dados. Neste caso, o endereço a ser exibido:

Diagrama de componentes

O LinearMemoryInspector se adiciona como um listener no LinearMemoryNavigator. A função addressChanged precisa ser acionada em um evento address-changed. Assim que o usuário estiver editando a entrada de endereço, o evento mencionado acima será enviado, e a função addressChanged será chamada. Essa função agora salva o endereço internamente e atualiza os subcomponentes usando um setter data(address, ..). Os subcomponentes salvam o endereço internamente e renderizam novamente as visualizações, mostrando o conteúdo nesse endereço específico.

Meta de design: fazer com que o desempenho e o consumo de memória sejam independentes do tamanho do buffer.

Durante o design do Inspetor de memória, um aspecto que tínhamos em mente era que o desempenho dele deveria ser independente do tamanho do buffer.

Como você viu na parte anterior, o componente LinearMemoryInspector usa uma UInt8Array para renderizar os valores. Ao mesmo tempo, queríamos ter certeza de que o Inspetor de memória não precisaria manter todos os dados, já que ele mostra apenas uma parte deles (por exemplo, a memória Wasm pode ter até 4 GB, e não queremos armazenar 4 GB no Inspetor de memória).

Assim, para garantir que a velocidade e o consumo de memória do Inspetor de memória sejam independentes do buffer real mostrado, permitimos que o componente LinearMemoryInspector mantenha apenas um subintervalo do buffer original.

Para que isso funcione, primeiro o LinearMemoryInspector precisa receber mais dois argumentos: um memoryOffset e um outerMemoryLength. O memoryOffset indica o deslocamento, em que o Uint8Array transmitido é iniciado, e é necessário para renderizar os endereços de dados corretos. O outerMemoryLength é o comprimento do buffer original e é necessário para entender qual intervalo podemos mostrar:

buffer

Com essas informações, podemos garantir que ainda seja possível renderizar a mesma visualização de antes (o conteúdo ao redor do address), sem realmente ter todos os dados no lugar. O que fazer se um endereço diferente for solicitado? Nesse caso, o LinearMemoryInspector aciona uma RequestMemoryEvent, que atualiza o intervalo atual que é mantido. Confira um exemplo abaixo:

Diagrama de fluxo do gatilho de evento

Neste exemplo, o usuário navega pela página de memória (o Inspetor de memória está usando paginação para mostrar blocos de dados), o que aciona uma PageNavigationEvent, que aciona uma RequestMemoryEvent. Esse evento inicia a busca do novo intervalo, que é propagado para o componente LinearMemoryInspector definindo os dados. Como resultado, exibimos os dados recém-buscados.

Ah, e você sabia? É possível até inspecionar a memória no código Wasm e C/C++

O Memory Inspector não está disponível apenas para ArrayBuffers em JavaScript, mas também pode ser usado para inspecionar a memória Wasm e a memória apontadas por referências/ponteiros C/C++ (usando nossa extensão DWARF. Faça um teste, caso ainda não tenha feito isso). Consulte Como depurar o WebAssembly com ferramentas modernas aqui. Uma pequena perspectiva do Inspetor de memória em ação para depuração nativa de C++ na Web:

Inspecionar a memória em C++

Conclusão

Este artigo apresentou o Inspetor de memória e mostrou um pouco do design dele. Esperamos que o Inspetor de memória ajude você a entender o que está acontecendo no ArrayBuffer :-). Se tiver sugestões para melhorá-lo, entre em contato e registre um bug.

Fazer o download dos canais de visualização

Use o Chrome Canary, Dev ou Beta como seu navegador de desenvolvimento padrão. Esses canais de pré-lançamento oferecem acesso aos recursos mais recentes do DevTools, testam as APIs modernas de plataformas da Web e encontram problemas no site antes dos usuários.

Entrar em contato com a equipe do Chrome DevTools

Use as opções a seguir para discutir os novos recursos e mudanças na publicação ou qualquer outra coisa relacionada ao DevTools.

  • Envie uma sugestão ou feedback em crbug.com.
  • Informe um problema do DevTools em Mais opções   Mais   > Ajuda > Informar problemas no DevTools.
  • Envie um tweet em @ChromeDevTools.
  • Deixe comentários nos nossos vídeos do YouTube sobre a ferramenta DevTools ou nos vídeos do YouTube com dicas sobre o DevTools.