Formato de archivo de instantánea del montón
La investigación del uso de memoria en aplicaciones web puede ser difícil. La herramienta Memoria de DevTools permite explorar todos los objetos asignados en memoria por la aplicación web mediante una instantánea de montón. Esta información es útil para las investigaciones de rendimiento, ya que puede averiguar qué objetos consumen más memoria.
Sin embargo, a veces es posible que tenga que centrarse en partes específicas de los datos de memoria que la herramienta Memoria no muestra. En este caso, use DevTools para exportar todo el conjunto de datos de memoria como un .heapsnapshot
archivo JSON.
En este artículo se describe la estructura y el contenido de .heapsnapshot
los archivos JSON para que pueda crear sus propias herramientas de visualización y análisis.
Registro de una instantánea de montón
Para exportar un .heapsnapshot
archivo, primero debe registrar una instantánea de montón en la herramienta Memoria , como se indica a continuación:
En Microsoft Edge, vaya al sitio web desde el que desea exportar los datos.
Presione Ctrl+Mayús+I (Windows, Linux) o Comando+Opción+I (macOS) para abrir Devtools.
Abra la herramienta Memoria .
Seleccione Instantánea de montón y, a continuación, haga clic en Tomar instantánea.
Para obtener más información, consulte Registro de instantáneas de montón mediante la herramienta Memoria ("Tipo de generación de perfiles instantánea de montón").
Exportación y visualización de un .heapsnapshot
archivo
Una vez que haya grabado una instantánea del montón, puede exportarla.
En la barra lateral izquierda de la herramienta Memoria , haga clic en Guardar junto al elemento de instantánea del montón que acaba de grabar.
Cambie la extensión de archivo de a
.json
, para facilitar la apertura del archivo en un editor de.heapsnapshot
texto.Abra el archivo guardado en un editor de texto, como Visual Studio Code.
Para facilitar la lectura del código JSON, en Visual Studio Code, haga clic con el botón derecho en cualquier lugar del código y, a continuación, seleccione Dar formato al documento.
Por lo general, el archivo resultante .heapsnapshot
es diferente cada vez que se registra y exporta una instantánea del montón. Las instantáneas de montón se generan dinámicamente, en función del contenido de la aplicación web que se está inspeccionando actualmente en DevTools.
Información general sobre el formato de .heapsnapshot
archivo
La memoria usada por una aplicación web se organiza como un grafo de V8, que es el motor de JavaScript que usa Microsoft Edge. Un gráfico es un tipo de datos que se compone de nodos (puntos en el gráfico) y bordes (vínculos entre los puntos).
Los datos del .heapsnapshot
archivo representan la memoria de la aplicación web que se gráfico de forma eficaz y facilita la transferencia de grupos de datos entre el proceso del explorador y DevTools. El .heapsnapshot
archivo contiene una representación plana de las relaciones entre nodos y bordes, como un objeto JSON que contiene matrices de números y cadenas. El archivo tiene una .heapsnapshot
extensión de nombre de archivo y contiene datos con formato JSON.
Los datos tienen dos partes principales:
- Los metadatos, que contienen toda la información necesaria para analizar las matrices de datos que representan el gráfico de memoria.
- Los datos de matrices, que contienen los datos reales necesarios para volver a crear el gráfico.
Actualización de esta documentación de formato de datos
El formato del .heapsnapshot
archivo, como se documenta a continuación, puede cambiar a medida que evolucionan V8 y DevTools. Si encuentra una discrepancia en la documentación, proporcione comentarios en el repositorio MicrosoftDocs/edge-developer.
Esquema de los .heapsnapshot
datos
Estructura de nivel superior
Los .heapsnapshot
datos JSON contienen un objeto raíz que tiene las siguientes propiedades:
{
"snapshot": {},
"nodes": [],
"edges": [],
"trace_function_infos": [],
"trace_tree": [],
"samples": [],
"locations": [],
"strings": []
}
Propiedad | Descripción | Formato |
---|---|---|
snapshot |
Contiene toda la información sobre el formato de los datos del gráfico de memoria y su tamaño. | Object |
nodes |
Toda la información necesaria para volver a crear los nodos del gráfico. Para analizar estos datos, use snapshot.meta.node_types y snapshot.meta.node_fields . |
Array |
edges |
Toda la información necesaria para volver a crear los bordes del gráfico. Para analizar estos datos, use snapshot.meta.edge_types y snapshot.meta.edge_fields . |
Array |
trace_function_infos |
Aún no documentado | Array |
trace_tree |
Aún no documentado | Array |
samples |
Aún no documentado | Array |
locations |
Contiene información sobre la ubicación del script de los nodos. Para analizar estos datos, use snapshot.meta.location_fields con la nodes matriz . |
Array |
strings |
Matriz de todas las cadenas que se conservan en la memoria. Pueden ser cualquier cadena, como cadenas definidas por el usuario o código. | Array |
Instantánea
{
"snapshot": {
"meta": {},
"node_count": 123,
"edge_count": 456,
"trace_function_count": 0
}
...
}
Propiedad | Descripción | Formato |
---|---|---|
meta |
Propiedades que contienen información sobre la forma y el tamaño de cada objeto contenido en los datos del gráfico de memoria. | Object |
node_count |
Número total de nodos en el gráfico de memoria. | Number |
edge_count |
Número total de bordes en el gráfico de memoria. | Number |
trace_function_count |
Número total de funciones de seguimiento en el gráfico de memoria. | Number |
Metadatos de instantáneas
{
"snapshot": {
"meta": {
"node_fields": [],
"node_types": [],
"edge_fields": [],
"edge_types": []
}
}
...
}
Propiedad | Descripción | Formato |
---|---|---|
node_fields |
Lista de todas las propiedades necesarias para volver a crear un nodo. | Array |
node_types |
Tipos de todas las propiedades necesarias para volver a crear un nodo. El número de tipos es el mismo que el número de propiedades definidas en node_fields . |
Array |
edge_fields |
Lista de todas las propiedades necesarias para volver a crear un borde. | Array |
edge_types |
Tipos de todas las propiedades necesarias para volver a crear un borde. El número de tipos es el mismo que el número de propiedades de edge_fields . |
Array |
A continuación se muestra un ejemplo de un objeto de metadatos:
{
"snapshot": {
"meta": {
"node_fields": [
"type",
"name",
"id",
"self_size",
"edge_count",
"trace_node_id",
"detachedness"
],
"node_types": [
[
"hidden",
"array",
"string",
"object",
"code",
"closure",
"regexp",
"number",
"native",
"synthetic",
"concatenated string",
"sliced string",
"symbol",
"bigint",
"object shape"
],
"string",
"number",
"number",
"number",
"number",
"number"
],
"edge_fields": [
"type",
"name_or_index",
"to_node"
],
"edge_types": [
[
"context",
"element",
"property",
"internal",
"hidden",
"shortcut",
"weak"
],
"string_or_number",
"node"
]
}
}
}
Nodes
La nodes
matriz, que se encuentra en el nivel superior de los .heapsnapshot
datos, contiene toda la información necesaria para volver a crear los nodos del gráfico de memoria.
Para analizar esta matriz, se necesita la siguiente información:
-
snapshot.node_count
, para saber cuántos nodos hay. -
snapshot.meta.node_fields
, para saber cuántos campos tiene cada nodo.
Cada nodo de la matriz se representa mediante una serie de snapshot.meta.node_fields.length
números. Por lo tanto, el número total de elementos de la nodes
matriz se snapshot.node_count
multiplica por snapshot.meta.node_fields.length
.
Para volver a crear un nodo, lea los números de la nodes
matriz por grupos de tamaño snapshot.meta.node_fields.length
.
El siguiente fragmento de código muestra los node_fields
metadatos y los datos de los dos primeros nodos del gráfico:
{
"snapshot": {
"meta": {
"node_fields": [
"type",
"name",
"id",
"self_size",
"edge_count",
"trace_node_id",
"detachedness"
]
...
}
...
},
"nodes": [
9,1,1,0,10,0,0,
2,1,79,12,1,0,0,
...
]
...
}
Índice en el grupo de nodos | Nombre | Descripción |
---|---|---|
0 |
type |
Tipo de nodo. Consulte Tipos de nodo, a continuación. |
1 |
name |
Nombre del nodo. Este es un número que es el índice de la matriz de nivel strings superior. Para buscar el nombre real, use el número de índice para buscar la cadena en la matriz de nivel strings superior. |
2 |
id |
Identificador único del nodo. |
3 |
self_size |
Tamaño del nodo en bytes. |
4 |
edge_count |
Número de bordes conectados a este nodo. |
5 |
trace_node_id |
Identificador del nodo de seguimiento |
6 |
detachedness |
Si se puede acceder a este nodo desde el window objeto global.
0 significa que el nodo no está desasociado; Se puede acceder al nodo desde el window objeto global.
1 significa que el nodo está desasociado; No se puede acceder al nodo desde el window objeto global. |
Tipos de nodo
El primer número del grupo de números de un nodo de la nodes
matriz corresponde a su tipo. Este número es un índice que se puede usar para buscar el nombre de tipo en la snapshot.meta.node_types[0]
matriz.
Tipo de nodo | Descripción |
---|---|
Hidden | Elemento interno V8 que no se corresponde directamente con un objeto JavaScript controlable por el usuario. En DevTools, todos se muestran bajo el nombre de categoría (sistema). Aunque estos objetos son internos, pueden ser una parte importante de las rutas de acceso de retención. |
Objeto | Cualquier objeto definido por el usuario, como { x: 2 } o new Foo(4) . Los contextos, que se muestran en DevTools como system/Context, contienen variables que tenían que asignarse en el montón porque las usa una función anidada. |
Nativa | Elementos asignados por el motor de representación de Blink, en lugar de por V8. Estos son principalmente elementos DOM, como HTMLDivElement o CSSStyleRule . |
Cadena concatenada | Resultado de concatenar dos cadenas con el + operador . En lugar de crear una nueva cadena que contenga una copia de todos los datos de las dos cadenas de origen, V8 crea un ConsString objeto que contiene punteros a las dos cadenas de origen. Desde una perspectiva de JavaScript, actúa igual que cualquier otra cadena, pero desde una perspectiva de generación de perfiles de memoria, es diferente. |
Cadena segmentada | Resultado de una operación de subcadena, como usar String.prototype.substr o String.prototype.substring . V8 evita copiar datos de cadena mediante la creación de , SlicedString que apunta a la cadena original y especifica el índice de inicio y la longitud. Desde una perspectiva de JavaScript, una cadena segmentada actúa como cualquier otra cadena, pero desde una perspectiva de generación de perfiles de memoria, es diferente. |
Matriz | Varias listas internas, que se muestran en DevTools con el nombre de categoría (matriz). Al igual que Hidden, esta categoría agrupa una variedad de cosas. Muchos de los objetos aquí se denominan (propiedades de objeto) o (elementos de objeto), lo que indica que contienen las propiedades con clave de cadena o con clave numérica de un objeto JavaScript. |
Código | Elementos que aumentan proporcionalmente a la cantidad de script o al número de veces que se ejecutan las funciones. |
Sintético | Los nodos sintéticos no se corresponden con nada realmente asignado en la memoria. Se usan para distinguir los distintos tipos de raíces de recolección de elementos no utilizados (GC). |
Bordes
De forma similar a la nodes
matriz, la edges
matriz de nivel superior contiene todos los elementos necesarios para volver a crear los bordes del gráfico de memoria.
También de forma similar a los nodos, el número total de bordes se puede calcular multiplicando snapshot.edge_count
por snapshot.meta.edge_fields.length
. Los bordes también se almacenan como una secuencia de números, en los que deberá recorrer en iteración por grupos de tamaño snapshot.meta.edge_fields.length
.
Sin embargo, para leer la edges
matriz correctamente, primero debe leer la nodes
matriz, ya que cada nodo sabe cuántos bordes tiene.
Para volver a crear un borde, necesita tres elementos de información:
- Tipo de borde.
- Nombre o índice perimetral.
- Nodo al que está conectado el perímetro.
Por ejemplo, si lee el primer nodo de la nodes
matriz y su edge_count
propiedad se establece en 4, los cuatro primeros grupos de números de snapshot.meta.edge_fields.length
la edges
matriz se corresponden con los cuatro bordes de este nodo.
Índice en grupo perimetral | Nombre | Descripción |
---|---|---|
0 |
type |
Tipo de borde. Consulte Tipos de Edge para averiguar cuáles son los tipos posibles. |
1 |
name_or_index |
Puede ser un número o una cadena. Si es un número, corresponde al índice de la matriz de nivel strings superior, donde se puede encontrar el nombre del borde. |
2 |
to_node |
Índice dentro de la matriz a la nodes que está conectado este borde. |
Tipos perimetrales
El primer número del grupo de números de un borde de la edges
matriz corresponde a su tipo. Este número es un índice que se puede usar para buscar el nombre de tipo en la snapshot.meta.edge_types[0]
matriz.
Tipo perimetral | Descripción |
---|---|
Interno | Los bordes que no se corresponden con nombres visibles de JavaScript, pero siguen siendo importantes. Por ejemplo, las instancias de Function tienen un "contexto" que representa el estado de las variables que estaban en el ámbito donde se definió la función. No hay ninguna manera de que el código JavaScript lea directamente el "contexto" de una función, pero estos bordes son necesarios al investigar los retenes. |
Débil | Los bordes débiles no mantienen activo el nodo al que están conectados y, por tanto, se omiten de la vista Retenedores. La recolección de elementos no utilizados (GC) puede descartar cualquier objeto con solo bordes débiles que apunten a él. |
Hidden | De forma similar a Interno, excepto que estos bordes no tienen nombres únicos y, en su lugar, se numeran en orden creciente. |
Acceso directo | Representación más fácil de leer de otra ruta de acceso. Este tipo se usa rara vez. Por ejemplo, si usa Function.prototype.bind para crear una función enlazada con algunos argumentos enlazados, V8 crea un JSBoundFunction , que apunta a ( FixedArray un tipo interno), que apunta a cada argumento enlazado. Al generar una instantánea, V8 agrega un borde de acceso directo de la función enlazada directamente a cada argumento enlazado, omitiendo .FixedArray |
Elemento | Propiedades del objeto donde la clave es un número. |
locations
La locations
matriz, que se encuentra en el nivel superior de los .heapsnapshot
datos, contiene información sobre dónde se crearon algunos de los nodos de la instantánea. Esta matriz consta de una serie de números destinados a ser leídos por grupos de tamaño snapshot.meta.location_fields.length
. Por lo tanto, vamos a snapshot.meta.location_fields
saber cuántos campos tiene cada ubicación de la locations
matriz y cuáles son esos campos. Por ejemplo, si location_fields
contiene 4 elementos, los grupos de 4 deben leer la locations
matriz.
snapshot.meta.location_fields
contiene la información de cada ubicación:
Índice en location_fields |
Nombre | Descripción |
---|---|---|
0 |
object_index |
Índice del nodo de la snapshot.nodes matriz asociada a esta ubicación. |
1 |
script_id |
Identificador del script que crea el nodo asociado. |
2 |
line |
Número de línea donde se creó el nodo, dentro del script que creó el nodo. |
3 |
column |
Número de columna donde se creó el nodo, dentro del script que creó el nodo. |
En el ejemplo de código siguiente se muestra cómo vincular la snapshot.locations
matriz a la snapshot.nodes
matriz:
{
"snapshot": {
"meta": {
"location_fields": [
"object_index",
"script_id",
"line",
"column"
]
...
}
...
},
"nodes": [
9,1,1,0,10,0,0,
2,1,79,12,1,0,0,
...
],
"locations":[
7,9,0,0,
113792,3,25,21,
...
],
...
}
La primera ubicación de la locations
matriz es 7,9,0,0,
. Esta ubicación está asociada al grupo de información de nodo que comienza en el índice 7 de la nodes
matriz. Por lo tanto, el nodo contiene los siguientes pares clave-valor:
"type": 2,
"name": 1,
"id": 79,
"self_size": 12,
"edge_count": 1,
"trace_node_id": 0,
"detachedness": 0,
"script_id": 9,
"line" 0,
"column": 0,
Vea también
Para obtener más información sobre el formato de .heapsnapshot
archivo, vea el código que genera el archivo, que es la HeapSnapshotGenerator
clase en heap-snapshot-generator.h
.