Memperbaiki masalah memori

Pelajari cara menggunakan Chrome dan DevTools untuk menemukan masalah memori yang memengaruhi performa halaman, termasuk kebocoran memori, penggelembungan memori, dan pengumpulan sampah yang sering.

Ringkasan

  • Ketahui berapa banyak memori yang saat ini digunakan halaman Anda dengan Pengelola Tugas Chrome.
  • Visualisasikan penggunaan memori dari waktu ke waktu dengan perekaman Linimasa.
  • Mengidentifikasi hierarki DOM yang terlepas (penyebab umum kebocoran memori) dengan Cuplikan Heap.
  • Cari tahu kapan memori baru dialokasikan di heap JS Anda dengan perekaman Allocation Linimasa.

Ringkasan

Sesuai dengan model performa RAIL, upaya peningkatan performa Anda harus berfokus pengguna Anda.

Masalah memori penting karena sering kali dapat dilihat oleh pengguna. Pengguna dapat merasakan memori masalah dengan cara berikut:

  • Performa halaman secara bertahap menjadi buruk seiring waktu. Ini mungkin merupakan gejala dari kebocoran memori. Kebocoran memori terjadi saat {i>bug<i} di laman menyebabkan laman menggunakan lebih banyak lebih banyak memori seiring waktu.
  • Performa halaman terus-menerus buruk. Ini mungkin merupakan gejala kegembungan memori. Memori penggelembungan terjadi saat halaman menggunakan memori lebih besar dari yang diperlukan untuk mengoptimalkan kecepatan halaman.
  • Performa halaman tertunda atau tampak sering dijeda. Ini mungkin merupakan gejala dari pembersihan sampah memori yang sering dilakukan. Pembersihan sampah memori adalah saat browser mengklaim kembali memori. Browser memutuskan kapan ini terjadi. Selama proses pengumpulan, semua eksekusi skrip akan dijeda. Jadi jika browser akan sering mengumpulkan sampah, eksekusi skrip akan sering dijeda.

Penggembungan memori: “terlalu banyak”?

Kebocoran memori mudah ditentukan. Jika sebuah situs secara progresif menggunakan lebih banyak memori, Anda telah mengalami kebocoran. Namun, penggelembungan memori agak lebih sulit untuk dijabarkan. Apa yang memenuhi syarat sebagai "menggunakan terlalu banyak memori"?

Tidak ada angka yang pasti di sini, karena perangkat dan browser yang berbeda memiliki kemampuan yang berbeda. Halaman yang sama yang berjalan mulus di ponsel pintar kelas atas bisa saja mogok di ponsel pintar kelas bawah.

Kuncinya di sini adalah menggunakan model RAIL dan fokus pada pengguna Anda. Cari tahu perangkat apa yang sedang populer dengan pengguna, lalu menguji laman Anda di perangkat tersebut. Jika pengalaman pengguna buruk, halaman mungkin melampaui kemampuan memori perangkat tersebut.

Memantau penggunaan memori secara realtime dengan Task Manager pada Chrome

Gunakan Pengelola Tugas Chrome sebagai titik awal untuk penyelidikan masalah memori Anda. {i>Task Manager<i} adalah pemantau real time yang memberi tahu Anda berapa banyak memori yang sedang digunakan sebuah laman.

  1. Tekan Shift+Esc atau buka menu utama Chrome dan pilih Alat lainnya > Task manager untuk buka {i>Task Manager<i}.

    Membuka Pengelola Tugas

  2. Klik kanan header tabel Task Manager dan aktifkan JavaScript memory.

    Mengaktifkan memori JS

Kedua kolom ini menunjukkan berbagai hal tentang cara halaman menggunakan memori:

  • Kolom Memori mewakili memori native. Node DOM disimpan di memori native. Jika ini nilainya meningkat, simpul DOM sedang dibuat.
  • Kolom Memori JavaScript mewakili heap JS. Kolom ini berisi dua nilai. Tujuan nilai yang Anda minati adalah angka aktual (angka dalam tanda kurung). Nomor aktual menunjukkan jumlah memori yang digunakan oleh objek yang dapat dijangkau di halaman Anda. Jika nomor ini meningkat, baik objek baru dibuat, atau objek yang ada bertambah.

Memvisualisasikan kebocoran memori dengan Rekaman performa

Anda juga dapat menggunakan panel Performa sebagai titik awal lainnya dalam penyelidikan. Performa membantu Anda memvisualisasikan penggunaan memori halaman dari waktu ke waktu.

  1. Buka panel Performa di DevTools.
  2. Aktifkan kotak centang Memory.
  3. Buat rekaman.

Untuk mendemonstrasikan perekaman memori performa, pertimbangkan kode di bawah ini:

var x = [];

function grow() {
  for (var i = 0; i < 10000; i++) {
    document.body.appendChild(document.createElement('div'));
  }
  x.push(new Array(1000000).join('x'));
}

document.getElementById('grow').addEventListener('click', grow);

Setiap kali tombol yang dirujuk dalam kode ditekan, sepuluh ribu node div akan ditambahkan ke isi dokumen, dan string yang terdiri dari satu juta karakter x dikirim ke array x. Menjalankan kode ini menghasilkan rekaman Linimasa seperti screenshot berikut:

contoh pertumbuhan sederhana

Pertama, penjelasan tentang antarmuka pengguna. Grafik HEAP di panel Overview (di bawah ini NET) mewakili heap JS. Di bawah panel Overview adalah panel Counter. Di sini, Anda dapat melihat penggunaan memori yang dikelompokkan berdasarkan heap JS (sama seperti grafik HEAP di panel Overview), dokumen, simpul DOM, pemroses, dan memori GPU. Menonaktifkan kotak centang akan menyembunyikannya dari grafik.

Sekarang, analisis kode dibandingkan dengan screenshot. Jika Anda melihat penghitung node ( grafik hijau) Anda dapat melihat bahwa itu cocok dengan kode. Jumlah {i>node<i} meningkat di langkah-langkah diskret. Anda dapat menganggap bahwa setiap peningkatan jumlah node adalah panggilan ke grow(). JS grafik heap (grafik biru) yang tidak mudah. Sesuai dengan praktik terbaik, penurunan pertama sebenarnya adalah pembersihan sampah memori paksa (dilakukan dengan menekan tombol kumpulkan sampah). Sebagai proses perekaman berlangsung, Anda bisa melihat ukuran heap JS melonjak. Hal ini wajar dan wajar: Kode JavaScript membuat simpul DOM setiap kali tombol diklik dan melakukan banyak pekerjaan saat itu menciptakan rangkaian yang terdiri dari satu juta karakter. Kuncinya di sini adalah fakta bahwa heap JS berakhir lebih tinggi dari awal ("awal" di sini adalah titik setelah pembersihan sampah memori paksa). Di beberapa di dunia nyata, jika Anda melihat pola peningkatan ukuran heap JS atau ukuran node, berpotensi menunjukkan kebocoran memori.

Menemukan kebocoran memori hierarki DOM yang terlepas dengan Heap Snapshots

Simpul DOM hanya bisa dibersihkan sampah memorinya jika tidak ada referensi ke sana dari hierarki DOM atau kode JavaScript. Sebuah node disebut sebagai "terpisah" ketika dihapus dari hierarki DOM tetapi beberapa JavaScript masih merujuknya. Simpul DOM yang terpisah merupakan penyebab umum kebocoran memori. Ini ini mengajarkan Anda cara menggunakan DevTools profiler heap untuk mengidentifikasi node yang terlepas.

Berikut contoh sederhana node DOM yang terlepas.

var detachedTree;

function create() {
  var ul = document.createElement('ul');
  for (var i = 0; i < 10; i++) {
    var li = document.createElement('li');
    ul.appendChild(li);
  }
  detachedTree = ul;
}

document.getElementById('create').addEventListener('click', create);

Mengklik tombol yang direferensikan dalam kode akan membuat node ul dengan sepuluh turunan li. Node ini direferensikan oleh kode, tetapi tidak ada di hierarki DOM, sehingga dilepas.

Snapshot heap adalah salah satu cara untuk mengidentifikasi node yang terlepas. Sesuai dengan namanya, cuplikan heap menunjukkan cara memori didistribusikan di antara objek JS halaman dan node DOM pada saat tanpa harus membuat snapshot.

Untuk membuat snapshot, buka DevTools dan buka panel Memory, pilih kolom Heap Tombol pilihan Snapshot, lalu tekan tombol Ambil Snapshot.

ambil snapshot heap

Mungkin perlu waktu beberapa saat untuk memproses dan memuat snapshot. Setelah selesai, pilih dari sebelah kiri (bernama HEAP SNAPSHOTS).

Ketikkan Detached di kotak teks Filter kelas untuk menelusuri hierarki DOM yang terlepas.

penyaringan untuk simpul yang terlepas

Luaskan karat untuk menyelidiki pohon yang terlepas.

menyelidiki pohon yang terlepas

Node yang ditandai dengan warna kuning memiliki referensi langsung dari kode JavaScript. Node ditandai merah tidak memiliki referensi langsung. Mereka hanya hidup karena mereka adalah bagian dari {i>node<i} kuning hierarki. Secara umum, Anda ingin berfokus pada node kuning. Perbaiki kode Anda agar simpul kuning tidak hidup lebih lama dari yang dibutuhkan, dan juga menyingkirkan simpul merah yang merupakan bagian dari pohon {i>node<i} kuning.

Klik node kuning untuk menyelidikinya lebih lanjut. Di panel Objects, Anda dapat melihat lebih banyak informasi tentang kode yang merujuknya. Misalnya, pada screenshot di bawah ini, Anda dapat melihat bahwa variabel detachedTree merujuk ke node tersebut. Untuk memperbaiki kebocoran memori ini, Anda akan mempelajari kode yang menggunakan detachedTree dan memastikan bahwa kode tersebut menghapus referensinya ke node saat tidak lagi diperlukan.

menyelidiki {i>node<i} kuning

Mengidentifikasi kebocoran memori heap JS dengan Allocation Linimasa

Allocation Linimasa adalah alat lain yang bisa membantu Anda melacak kebocoran memori di heap JS.

Untuk mendemonstrasikan Linimasa Alokasi, pertimbangkan kode berikut:

var x = [];

function grow() {
  x.push(new Array(1000000).join('x'));
}

document.getElementById('grow').addEventListener('click', grow);

Setiap kali tombol yang dirujuk dalam kode ditekan, string berisi satu juta karakter ditambahkan ke array x.

Untuk merekam Allocation Linimasa, buka DevTools, buka panel Profiles, pilih Record Tombol pilihan Allocation Linimasa, tekan tombol Start, lakukan tindakan yang Anda duga menyebabkan kebocoran memori, lalu tekan tombol berhenti merekam (tombol berhenti merekam) saat selesai.

Selagi Anda merekam, perhatikan apakah ada bilah biru yang muncul di Allocation Linimasa, seperti di screenshot di bawah.

alokasi baru

Bilah biru tersebut merepresentasikan alokasi memori baru. Alokasi memori baru tersebut adalah kandidat Anda karena kebocoran memori. Anda dapat memperbesar batang untuk memfilter panel Konstruktor agar hanya menampilkan objek yang dialokasikan selama jangka waktu yang ditentukan.

linimasa alokasi yang diperbesar

Luaskan objek dan klik nilainya untuk melihat detail selengkapnya tentangnya di panel Object. Sebagai contoh, dalam tangkapan layar di bawah, dengan melihat detail objek yang baru dialokasikan, Anda dapat melihat bahwa variabel tersebut dialokasikan ke variabel x dalam cakupan Window.

detail objek

Menginvestigasi alokasi memori berdasarkan fungsi

Gunakan jenis Allocation Sampling di panel Memory untuk melihat alokasi memori berdasarkan fungsi JavaScript.

Rekam Profiler Alokasi

  1. Pilih tombol pilihan Allocation Sampling. Jika ada pekerja pada halaman, Anda dapat memilihnya sebagai target pembuatan profil dengan menggunakan menu dropdown di samping tombol Start.
  2. Tekan tombol Start.
  3. Lakukan tindakan pada halaman yang ingin Anda selidiki.
  4. Tekan tombol Stop setelah Anda menyelesaikan semua tindakan.

DevTools menampilkan perincian alokasi memori berdasarkan fungsi. Tampilan defaultnya adalah Berat (Bawah Atas), yang menampilkan fungsi yang mengalokasikan memori paling banyak di bagian atas.

Profil alokasi

Menemukan pembersihan sampah memori yang sering dilakukan

Jika halaman Anda tampak sering dijeda, mungkin Anda mengalami masalah pembersihan sampah memori.

Anda dapat menggunakan Pengelola Tugas Chrome atau perekaman memori Linimasa untuk mencari sampah yang sering koleksi baru. Di Pengelola Tugas, Memori atau Memori JavaScript yang sering naik-turun nilai yang mewakili pengumpulan sampah yang sering. Dalam rekaman Linimasa, peristiwa naik dan turun yang sering Grafik heap JS atau jumlah node menunjukkan pembersihan sampah memori yang sering.

Setelah mengidentifikasi masalahnya, Anda dapat menggunakan rekaman Linimasa Alokasi untuk mencari tahu di mana memori yang dialokasikan dan fungsi mana yang menyebabkan alokasi tersebut.