Scopri come registrare snapshot dell'heap con Memoria > Profili > Istantanea dell'heap e trova le perdite di memoria.
Il profiler heap mostra la distribuzione della memoria in base agli oggetti JavaScript della tua pagina e ai nodi DOM correlati. Utilizzalo per creare snapshot heap JS, analizzare grafici di memoria, confrontare snapshot e trovare perdite di memoria. Per ulteriori informazioni, consulta Albero di conservazione degli oggetti.
Scatta una foto
Per creare un'istantanea dell'heap:
- Nella pagina che vuoi profilare, apri DevTools e vai al riquadro Memoria.
- Seleziona il tipo di profilazione Istantanea heap, seleziona un'istanza VM JavaScript e fai clic su Crea snapshot.
Quando il riquadro Memoria carica e analizza l'istantanea, mostra le dimensioni totali degli oggetti JavaScript raggiungibili sotto il titolo dell'istantanea nella sezione ISTANTEANEE HEAP.
Gli snapshot mostrano solo gli oggetti del grafico della memoria che sono raggiungibili dall'oggetto globale. L'acquisizione di uno snapshot inizia sempre con la garbage collection.
Cancella istantanee
Per rimuovere tutte le istantanee, fai clic su
Cancella tutti i profili:Visualizza snapshot
Per esaminare le istantanee da diverse prospettive per scopi diversi, seleziona una delle visualizzazioni dal menu a discesa in alto:
Visualizza | Contenuti | Finalità |
---|---|---|
Riepilogo | Oggetti raggruppati per nomi dei costruttori. | da usare per scovare oggetti e la loro memoria utilizzata in base al tipo. È utile per monitorare le fughe di dati nel DOM. |
Confronto | Differenze tra due snapshot. | Utilizzala per confrontare due (o più) snapshot prima e dopo un'operazione. Conferma la presenza e la causa di una perdita di memoria esaminando il delta nella memoria libera e nel conteggio dei riferimenti. |
Contenimento | Contenuti heap | Fornisce una visione migliore della struttura degli oggetti e consente di analizzare gli oggetti a cui viene fatto riferimento nello spazio dei nomi globale (finestra) per trovare ciò che li mantiene. Utilizzala per analizzare le chiusure e immergerti negli oggetti a basso livello. |
Statistiche | Grafico a torta dell'allocazione della memoria | Osserva le dimensioni reali delle parti di memoria allocate a codice, stringhe, array JS, array digitati e oggetti di sistema. |
Visualizzazione riepilogo
Inizialmente, si apre un'istantanea dell'heap nella visualizzazione Riepilogo in cui sono elencati i costruttori in una colonna. Puoi espandere i costruttori per visualizzare gli oggetti di cui hanno creato un'istanza.
Per filtrare i costruttori non pertinenti, digita un nome che vuoi esaminare nel filtro del corso nella parte superiore della vista Riepilogo.
I numeri accanto ai nomi dei costruttori indicano il numero totale di oggetti creati con il costruttore. La visualizzazione Riepilogo mostra anche le seguenti colonne:
- Distanza mostra la distanza alla radice utilizzando il percorso semplice più breve di nodi.
- Dimensioni superficiali mostra la somma delle dimensioni di tutti gli oggetti creati da un determinato costruttore. La dimensione superficiale è la dimensione della memoria di un oggetto stesso. In genere, array e stringhe hanno dimensioni superficiali più grandi. Vedi anche Dimensioni degli oggetti.
- Dimensioni conservate mostra le dimensioni massime conservate nello stesso insieme di oggetti. La dimensione conservata è la dimensione della memoria che si può liberare eliminando un oggetto e rendendo i suoi dipendenti non più raggiungibili. Vedi anche Dimensioni degli oggetti.
Quando espandi un costruttore, la visualizzazione Riepilogo mostra tutte le sue istanze. Ogni istanza riceve un'analisi delle sue dimensioni di base e conservate nelle colonne corrispondenti. Il numero dopo il carattere @
rappresenta l'ID univoco dell'oggetto. Consente di confrontare gli snapshot dell'heap per singolo oggetto.
Filtri costruttore
La vista Riepilogo consente di filtrare i costruttori in base ai casi comuni di utilizzo della memoria inefficiente.
Per utilizzare questi filtri, seleziona una delle seguenti opzioni dal menu a discesa all'estrema destra nella barra delle azioni:
- Tutti gli oggetti: tutti gli oggetti acquisiti dallo snapshot corrente. Impostazione predefinita.
- Oggetti allocati prima dello snapshot 1: oggetti creati e rimasti in memoria prima dell'acquisizione del primo snapshot.
- Oggetti allocati tra snapshot 1 e snapshot 2: visualizza la differenza di oggetti tra lo snapshot più recente e quello precedente. Ogni nuovo snapshot aggiunge un incremento di questo filtro all'elenco a discesa.
- Stringhe duplicate: valori di stringa che sono stati archiviati più volte in memoria.
- Oggetti conservati da nodi scollegati: oggetti che vengono mantenuti attivi perché un nodo DOM scollegato vi fa riferimento.
- Oggetti conservati dalla console DevTools: oggetti conservati in memoria perché sono stati valutati o con cui sono stati oggetto di interazione tramite la console DevTools.
Voci speciali nel riepilogo
Oltre a raggruppare gli oggetti per costruttore, la visualizzazione Riepilogo raggruppa gli oggetti anche in base a:
- Funzioni integrate come
Array
oObject
. - Elementi HTML raggruppati in base ai tag, ad esempio
<div>
,<a>
,<img>
e altri. - Funzioni definite nel codice.
- Categorie speciali non basate su costruttori.
(array)
Questa categoria include vari oggetti di tipo array interni che non corrispondono direttamente agli oggetti visibili in JavaScript.
Ad esempio, i contenuti degli oggetti JavaScript Array
vengono archiviati in un oggetto interno secondario denominato (object elements)[]
, per consentire il ridimensionamento più semplice. Allo stesso modo, le proprietà con nome negli oggetti JavaScript vengono spesso archiviate in oggetti interni secondari denominati (object properties)[]
elencati anche nella categoria (array)
.
(compiled code)
Questa categoria include i dati interni necessari a V8 per poter eseguire funzioni definite da JavaScript o WebAssembly. Ogni funzione può essere rappresentata in vari modi, da piccole e lente a grandi e veloci.
V8 gestisce automaticamente l'utilizzo della memoria in questa categoria. Se una funzione viene eseguita molte volte, V8 utilizza più memoria per quella funzione, in modo che possa essere eseguita più velocemente. Se una funzione non viene eseguita da un po' di tempo, V8 potrebbe cancellare i relativi dati interni.
(concatenated string)
Quando V8 concatena due stringhe, ad esempio con l'operatore JavaScript +
, può scegliere di rappresentare internamente il risultato come "stringa concatenata" anche nota come struttura dati Rope.
Anziché copiare tutti i caratteri delle due stringhe di origine in una nuova stringa, V8 assegna un piccolo oggetto con campi interni chiamati first
e second
, che puntano alle due stringhe di origine. Ciò consente a V8 di risparmiare tempo e memoria. Dal punto di vista del codice JavaScript, si tratta semplicemente di stringhe normali che si comportano come qualsiasi altra stringa.
InternalNode
Questa categoria rappresenta gli oggetti allocati al di fuori di V8, ad esempio gli oggetti C++ definiti da Blink.
Per visualizzare i nomi delle classi C++, utilizza Chrome for Testing ed esegui le seguenti operazioni:
- Apri DevTools e attiva le Impostazioni > Esperimenti > Mostra l'opzione per esporre gli elementi interni negli snapshot dell'heap.
- Apri il riquadro Memoria, seleziona Istantanea dell'heap e attiva Esponi dati interni (include dettagli aggiuntivi specifici per l'implementazione).
- Riproduci il problema per cui
InternalNode
ha conservato molta memoria. - Acquisisci un'istantanea dell'heap. In questo snapshot, gli oggetti hanno nomi di classi C++ anziché
InternalNode
.
(object shape)
Come descritto in Proprietà rapide in V8, V8 tiene traccia delle classi (o forme) nascoste in modo che più oggetti con le stesse proprietà nello stesso ordine possano essere rappresentati in modo efficiente. Questa categoria contiene le classi nascoste, denominate system / Map
(non correlate a JavaScript Map
) e i dati correlati.
(sliced string)
Quando V8 deve prendere una sottostringa, ad esempio quando il codice JavaScript chiama String.prototype.substring()
, V8 può scegliere di allocare un oggetto stringa segmentata anziché copiare tutti i caratteri pertinenti dalla stringa originale. Questo nuovo oggetto contiene un puntatore alla stringa originale e descrive quale intervallo di caratteri della stringa originale utilizzare.
Dal punto di vista del codice JavaScript, si tratta di normali stringhe che si comportano come qualsiasi altra stringa. Se una stringa suddivisa occupa molta memoria, il programma potrebbe aver attivato il problema 2869 e potrebbe trarre vantaggio dall'adozione di misure deliberate per "appiattire" la stringa suddivisa.
system / Context
Gli oggetti interni di tipo system / Context
contengono variabili locali di una chiusura, ovvero un ambito JavaScript a cui può accedere una funzione nidificata.
Ogni istanza di funzione contiene un puntatore interno al Context
in cui viene eseguita, in modo che possa accedere a queste variabili. Anche se gli oggetti Context
non sono direttamente visibili da JavaScript, hai il controllo diretto su di essi.
(system)
Questa categoria contiene vari oggetti interni che non sono (ancora) stati classificati in modo più significativo.
Vista di confronto
La vista Confronto ti consente di trovare gli oggetti divulgati confrontando più snapshot tra loro. Ad esempio, eseguire un'azione e invertirla, come aprire e chiudere un documento, non dovrebbe lasciare oggetti aggiuntivi.
Per verificare che una determinata operazione non crei perdite:
- Acquisisci uno snapshot dell'heap prima di eseguire un'operazione.
- Eseguire un'operazione. In altre parole, interagisci con la pagina in un modo che ritieni possa causare una fuga di dati.
- Esegui un'operazione inversa. Vale a dire che devi fare l'interazione opposta e ripeterla alcune volte.
- Acquisisci una seconda istantanea dell'heap e modificane la visualizzazione in Confronto, confrontandola con Istantanea 1.
La vista Confronto mostra la differenza tra due istantanee. Quando espandi un totale vengono visualizzate le seguenti istanze di oggetti:
Vista di contenimento
La visualizzazione Contenimento è una "panoramica" della struttura degli oggetti dell'applicazione. Ti consente di dare un'occhiata all'interno delle chiusure delle funzioni, osservare gli oggetti interni delle VM che insieme costituiscono gli oggetti JavaScript e comprendere quanta memoria viene utilizzata dall'applicazione a un livello molto basso.
La visualizzazione offre diversi punti di contatto:
- Oggetti DOMWindow. Oggetti globali per il codice JavaScript.
- Radici GC. Radici GC utilizzate dal garbage collector della VM. Le radici del GC possono essere costituite da mappe di oggetti integrate, tabelle di simboli, stack di thread VM, cache di compilazione, ambiti di handle e handle globali.
- Oggetti nativi. Oggetti del browser con "push" all'interno della macchina virtuale JavaScript per consentire l'automazione, ad esempio nodi DOM e regole CSS.
Sezione Retainer
La sezione Retainer nella parte inferiore del riquadro Memoria mostra gli oggetti che puntano all'oggetto selezionato nella visualizzazione. Il riquadro Memoria aggiorna la sezione Retainer quando selezioni un oggetto diverso in una delle viste, ad eccezione di Statistiche.
In questo esempio, la stringa selezionata viene mantenuta dalla proprietà x
di un'istanza Item
.
Ignora elementi di conservazione
Puoi nascondere gli elementi di conservazione per scoprire se tra gli altri oggetti viene mantenuto quello selezionato. Con questa opzione, non è necessario rimuovere prima questo elemento di conservazione dal codice e poi acquisire nuovamente lo snapshot dell'heap.
Per nascondere un fermo, fai clic con il tasto destro del mouse e seleziona Ignora questo fermo. I retainer ignorati sono contrassegnati come ignored
nella colonna Distanza. Per non ignorare più tutti gli elementi di conservazione, fai clic su Ripristina elementi di conservazione ignorati nella barra delle azioni in alto.
Trovare un oggetto specifico
Per trovare un oggetto nell'heap raccolto, puoi cercare utilizzando Ctrl + F e inserire l'ID oggetto.
Assegna un nome alle funzioni per distinguere le chiusure
È molto utile nominare le funzioni in modo da poter distinguere le chiusure nell'istantanea.
Ad esempio, il seguente codice non utilizza funzioni con nome:
function createLargeClosure() {
var largeStr = new Array(1000000).join('x');
var lC = function() { // this is NOT a named function
return largeStr;
};
return lC;
}
Mentre in questo esempio:
function createLargeClosure() {
var largeStr = new Array(1000000).join('x');
var lC = function lC() { // this IS a named function
return largeStr;
};
return lC;
}
Individuare le fughe di notizie nel DOM
Il profiler heap è in grado di riflettere le dipendenze bidirezionali tra oggetti nativi del browser (nodi DOM e regole CSS) e oggetti JavaScript. Ciò consente di scoprire fughe di dati altrimenti invisibili a causa di sottoalberi DOM dimenticati che fluttuano in giro.
Le fughe di dati nel DOM possono essere maggiori di quanto pensi. Considera l'esempio seguente: Quando viene raccolta la spazzatura #tree
?
var select = document.querySelector;
var treeRef = select("#tree");
var leafRef = select("#leaf");
var body = select("body");
body.removeChild(treeRef);
//#tree can't be GC yet due to treeRef
treeRef = null;
//#tree can't be GC yet due to indirect
//reference from leafRef
leafRef = null;
//#NOW #tree can be garbage collected
#leaf
mantiene un riferimento al proprio elemento principale (parentNode
) e in modo ricorsivo fino a #tree
, quindi solo
Quando leafRef
viene annullato, l'intero albero in #tree
è un candidato per la carica di Garbage Collection.