Presentación del Inspector de memoria

Kim-Anh Tran
Kim-Anh Tran

En este artículo, se presenta el Inspector de memoria que llegó a Chrome 91. Te permite inspeccionar tu ArrayBuffer, TypedArray, DataView y la memoria Wasm.

Introducción

¿Alguna vez quisiste comprender los datos de tu ArrayBuffer? Antes del Inspector de memoria, Herramientas para desarrolladores solo permitía realizar estadísticas limitadas sobre ArrayBuffers. La inspección desde la vista Scope durante una sesión de depuración se limitaba a ver una lista de valores únicos dentro del búfer del array, lo que dificultaba comprender los datos en su conjunto. A modo de ejemplo, la vista Scope muestra el búfer como rangos expandibles de arrays en el siguiente ejemplo:

Vista de permisos en Herramientas para desarrolladores

Navegar a un rango determinado dentro del búfer era una dificultad, ya que requería que el usuario se desplazara hacia abajo para finalmente llegar a ese índice. Pero incluso aunque navegar a una posición sea fácil, esta manera de inspecting los valores es engorrosa: es difícil saber qué significan estos números. En particular, ¿qué sucede si no deben interpretarse como bytes únicos, sino como números enteros de 32 bits?

Cómo inspeccionar valores con el Inspector de memoria

Inspector de memoria

En Chrome 91, presentamos el Inspector de memoria, una herramienta para inspeccionar búferes de arrays. Es posible que ya hayas visto herramientas de inspección de memoria para ver datos binarios, que muestran el contenido binario en una cuadrícula junto con sus direcciones, y que ofrecen diferentes maneras de interpretar los valores subyacentes. Esto es lo que el Inspector de memoria te ofrece. Con el Inspector de memoria, ahora puedes ver el contenido, navegar por él y seleccionar los tipos que se usarán para interpretar los valores a mano. Muestra los valores ASCII directamente junto a los bytes y permite al usuario seleccionar diferentes valores endian. A continuación, observa el funcionamiento del Inspector de memoria:

¿Quieres probarla? Si quieres obtener información para abrir el Inspector de memoria y ver el búfer de array (o TypedArray, DataView o Wasm Memory), y obtener más información sobre su uso, consulta nuestra documentación sobre el Inspector de memoria. Prueba estos ejemplos (para JS, Wasm y C++).

Cómo diseñar el Inspector de memoria

En esta parte, veremos cómo se diseña el Inspector de memoria con componentes web y te mostraremos uno de los objetivos de diseño que teníamos y cómo lo implementamos. Si tienes curiosidad y quieres ver más, consulta nuestro documento de diseño para el Inspector de memoria.

Es posible que hayas visto nuestra entrada de blog sobre Cómo migrar a componentes web, donde Jack publicó nuestra guía interna sobre cómo compilar componentes de IU con componentes web. La migración a componentes web coincidió con nuestro trabajo en el Inspector de memoria y, como resultado, decidimos probar el nuevo sistema. A continuación, se muestra un diagrama que muestra los componentes que compilamos para crear el Inspector de memoria (ten en cuenta que internamente lo llamamos Linear Memory Inspector):

Componentes web

LinearMemoryInspector es el componente superior que combina los subcomponentes que generan todos los elementos en el Inspector de memoria. Básicamente, toma una Uint8Array y una address y, con cada cambio de cualquiera de ellas, se propagan los datos a sus elementos secundarios, lo que activa una nueva renderización. El LinearMemoryInspector renderiza tres subcomponentes:

  1. LinearMemoryViewer (se muestran los valores)
  2. LinearMemoryNavigator (que permite la navegación)
  3. LinearMemoryValueInterpreter (que muestra diferentes interpretaciones de tipo de los datos subyacentes)

El último es un componente superior, que renderiza el ValueInterpreterDisplay (que muestra los valores) y el ValueInterpreterSettings (selecciona qué tipos ver en la pantalla).

Cada uno de los componentes está diseñado para representar solo un pequeño componente de la IU, de modo que los componentes se puedan volver a usar si es necesario. Cuando se establecen datos nuevos en un componente, se activa una nueva renderización que muestra el cambio reflejado en los datos establecidos en el componente. A continuación, se muestra un ejemplo de un flujo de trabajo con nuestros componentes, donde el usuario cambia la dirección en la barra de direcciones, lo que activa una actualización configurando los nuevos datos, en este caso la dirección a ver:

Diagrama de componentes

LinearMemoryInspector se agrega a sí mismo como objeto de escucha en LinearMemoryNavigator. La función addressChanged se activará en un evento address-changed. No bien el usuario edita la entrada de dirección, se envía el evento mencionado anteriormente, de modo que se llame a la función addressChanged. Esta función ahora guarda la dirección internamente y actualiza sus subcomponentes con un método set data(address, ..). Los subcomponentes guardan la dirección internamente y vuelven a renderizar sus vistas para mostrar el contenido de esa dirección en particular.

Objetivo de diseño: Hacer que el rendimiento y el consumo de memoria sean independientes del tamaño del búfer

Un aspecto que tuvimos en cuenta durante el diseño del Inspector de memoria era que su rendimiento debía ser independiente del tamaño del búfer.

Como viste en la parte anterior, el componente LinearMemoryInspector toma una UInt8Array para renderizar los valores. Al mismo tiempo, queríamos asegurarnos de que el Inspector de memoria no necesitara almacenar todos los datos, ya que solo muestra una parte de ellos (p.ej., la memoria Wasm puede tener un tamaño de hasta 4 GB, y no queremos almacenar 4 GB en el Inspector de memoria).

Por lo tanto, para garantizar que la velocidad y el consumo de memoria del Inspector de memoria sean independientes del búfer real que mostramos, permitimos que el componente LinearMemoryInspector solo mantenga un subrango del búfer original.

Para que esto funcione, LinearMemoryInspector primero debe tomar dos argumentos más: memoryOffset y outerMemoryLength. El memoryOffset indica el desplazamiento, en el que se inicia el Uint8Array pasado, y es necesario para renderizar las direcciones de datos correctas. outerMemoryLength es la longitud del búfer original y es necesario para comprender qué rango podemos mostrar:

búfer

Con esta información, podemos asegurarnos de que podamos renderizar la misma vista que antes (el contenido alrededor de address), sin tener todos los datos en su lugar. Entonces, ¿qué hacer si se solicita una dirección diferente, que entra en un rango diferente? En ese caso, LinearMemoryInspector activa un RequestMemoryEvent, que actualiza el rango actual que se mantiene. A continuación, se muestra un ejemplo:

Diagrama de flujo del activador de eventos

En este ejemplo, el usuario navega por la página de memoria (el Inspector de memoria usa la paginación para mostrar fragmentos de datos), lo que activa un PageNavigationEvent, que activa un RequestMemoryEvent. Ese evento inicia la recuperación del nuevo rango, que luego se propaga al componente LinearMemoryInspector mediante la configuración de los datos. Como resultado, mostramos los datos recién recuperados.

¿Y lo sabías? Incluso puedes inspeccionar memoria en código Wasm y C/C++

El Inspector de memoria no solo está disponible para ArrayBuffers en JavaScript, sino que también se puede usar para inspeccionar memoria Wasm y memoria a la que apuntan referencias o punteros C/C++ (con nuestra extensión DWARF; pruébala si aún no lo has hecho). Consulta Cómo depurar WebAssembly con herramientas modernas aquí. Una pequeña mirada del Inspector de memoria en acción para la depuración nativa de C++ en la Web:

Cómo inspeccionar memoria en C++

Conclusión

En este artículo, se presentó el Inspector de memoria y se mostró un vistazo de su diseño. Esperamos que el Inspector de memoria te ayude a comprender lo que sucede en tu ArrayBuffer :-. Si tienes sugerencias para mejorarlo, avísanos y informa un error.

Descarga los canales de vista previa

Considera usar Canary, Dev o Beta de Chrome como tu navegador de desarrollo predeterminado. Estos canales de vista previa te brindan acceso a las funciones más recientes de Herramientas para desarrolladores, prueba APIs de plataformas web de vanguardia y encuentra problemas en tu sitio antes que tus usuarios.

Cómo comunicarse con el equipo de Herramientas para desarrolladores de Chrome

Usa las siguientes opciones para analizar las nuevas funciones y los cambios en la publicación, o cualquier otra cosa relacionada con Herramientas para desarrolladores.

  • Envíanos tus sugerencias o comentarios a través de crbug.com.
  • Informa un problema en Herramientas para desarrolladores mediante Más opciones   Más   > Ayuda > Informar problemas con Herramientas para desarrolladores en Herramientas para desarrolladores.
  • Envía un tweet a @ChromeDevTools.
  • Deja comentarios en los videos de YouTube de las Novedades de las Herramientas para desarrolladores o en las sugerencias de Herramientas para desarrolladores (videos de YouTube).