Saya telah membuat test case yang sangat sederhana yang menciptakan tampilan Backbone, melampirkan handler ke suatu peristiwa, dan membuat instance kelas yang ditentukan pengguna. Saya percaya bahwa dengan mengklik tombol "Hapus" dalam sampel ini, semuanya akan dibersihkan dan seharusnya tidak ada kebocoran memori.
Jsfiddle untuk kode ada di sini: http://jsfiddle.net/4QhR2/
// scope everything to a function
function main() {
function MyWrapper() {
this.element = null;
}
MyWrapper.prototype.set = function(elem) {
this.element = elem;
}
MyWrapper.prototype.get = function() {
return this.element;
}
var MyView = Backbone.View.extend({
tagName : "div",
id : "view",
events : {
"click #button" : "onButton",
},
initialize : function(options) {
// done for demo purposes only, should be using templates
this.html_text = "<input type='text' id='textbox' /><button id='button'>Remove</button>";
this.listenTo(this,"all",function(){console.log("Event: "+arguments[0]);});
},
render : function() {
this.$el.html(this.html_text);
this.wrapper = new MyWrapper();
this.wrapper.set(this.$("#textbox"));
this.wrapper.get().val("placeholder");
return this;
},
onButton : function() {
// assume this gets .remove() called on subviews (if they existed)
this.trigger("cleanup");
this.remove();
}
});
var view = new MyView();
$("#content").append(view.render().el);
}
main();
Namun, saya tidak jelas bagaimana cara menggunakan profiler Google Chrome untuk memverifikasi bahwa ini adalah kenyataannya. Ada trilyun hal yang muncul di snapshot profiler tumpukan, dan saya tidak tahu bagaimana untuk memecahkan kode apa yang baik / buruk. Tutorial yang saya lihat sejauh ini hanya memberi tahu saya untuk "menggunakan snapshot profiler" atau memberi saya manifesto yang sangat rinci tentang cara kerja seluruh profiler. Apakah mungkin hanya menggunakan profiler sebagai alat, atau apakah saya benar-benar harus memahami bagaimana semuanya direkayasa?
EDIT: Tutorial seperti ini:
Memperbaiki kebocoran memori Gmail
Merupakan perwakilan dari beberapa materi kuat di luar sana, dari apa yang saya lihat. Namun, di luar memperkenalkan konsep 3 Snapshot Technique , saya menemukan mereka menawarkan sangat sedikit dalam hal pengetahuan praktis (untuk pemula seperti saya). Tutorial 'Menggunakan DevTools' tidak bekerja melalui contoh nyata, jadi deskripsi konseptualnya yang kabur dan umum tidak terlalu membantu. Adapun contoh 'Gmail':
Jadi Anda menemukan kebocoran. Sekarang apa?
Periksa jalur penahan benda bocor di bagian bawah panel Profil
Jika situs alokasi tidak dapat disimpulkan dengan mudah (mis. Pendengar acara):
Instrumen konstruktor objek penahan melalui konsol JS untuk menyimpan jejak stack untuk alokasi
Menggunakan Penutupan? Aktifkan flag yang sesuai yang ada (yaitu goog.events.Listener.ENABLE_MONITORING) untuk mengatur properti creationStack selama konstruksi
Saya menemukan diri saya lebih bingung setelah membaca itu, tidak kurang. Dan, sekali lagi, ini hanya memberitahu saya untuk melakukan sesuatu, bukan bagaimana melakukannya. Dari sudut pandang saya, semua informasi di luar sana terlalu samar atau hanya akan masuk akal bagi seseorang yang sudah memahami prosesnya.
Beberapa masalah yang lebih spesifik ini telah diangkat dalam jawaban @Jonathan Naguin di bawah ini.
sumber
main
10.000 kali, bukan sekali, dan melihat apakah Anda memiliki lebih banyak memori yang digunakan di akhir.Jawaban:
Alur kerja yang baik untuk menemukan kebocoran memori adalah teknik snapshot tiga , pertama kali digunakan oleh Loreena Lee dan tim Gmail untuk menyelesaikan beberapa masalah memori mereka. Langkah-langkahnya adalah, secara umum:
Sebagai contoh Anda, saya telah mengadaptasi kode untuk menunjukkan proses ini (Anda dapat menemukannya di sini ) menunda pembuatan Backbone View hingga acara klik tombol Start. Sekarang:
Sekarang Anda siap menemukan kebocoran memori!
Anda akan melihat beberapa warna yang berbeda. Node merah tidak memiliki referensi langsung dari Javascript kepada mereka, tetapi masih hidup karena mereka adalah bagian dari pohon DOM yang terpisah. Mungkin ada simpul di pohon yang dirujuk dari Javascript (mungkin sebagai penutupan atau variabel) tetapi secara kebetulan mencegah seluruh pohon DOM dari sampah yang dikumpulkan.
Namun node kuning memiliki referensi langsung dari Javascript. Cari node kuning di pohon DOM terpisah yang sama untuk mencari referensi dari Javascript Anda. Harus ada rantai properti yang mengarah dari jendela DOM ke elemen.
Secara khusus, Anda dapat melihat elemen HTML Div ditandai dengan warna merah. Jika Anda memperluas elemen Anda akan melihat yang direferensikan oleh fungsi "cache".
Pilih baris dan di konsol Anda ketik $ 0, Anda akan melihat fungsi dan lokasi aktual:
Di sinilah elemen Anda dirujuk. Sayangnya tidak banyak yang dapat Anda lakukan, ini adalah mekanisme internal dari jQuery. Tapi, hanya untuk tujuan pengujian, buka fungsinya dan ubah metode menjadi:
Sekarang jika Anda mengulangi prosesnya Anda tidak akan melihat simpul merah :)
Dokumentasi:
sumber
$0
fungsi di konsol, yang baru bagi saya - tentu saja, saya tidak tahu apa yang sedang dilakukan atau bagaimana Anda tahu menggunakannya ($1
tampaknya tidak berguna sementara$2
tampaknya melakukan hal yang sama). Kedua, bagaimana Anda tahu untuk menyorot baris#button in function cache()
dan bukan dari puluhan baris lainnya? Akhirnya, ada simpul merah di dalamNodeList
danHTMLInputElement
juga, tapi saya tidak bisa mengetahuinya.cache
baris berisi informasi sementara yang lain tidak? Ada banyak cabang yang memiliki jarak lebih rendah dari yangcache
satu itu. Dan saya tidak yakin bagaimana Anda tahu bahwa ituHTMLInputElement
adalah anak dariHTMLDivElement
. Saya melihatnya direferensikan di dalamnya ("asli dalam HTMLDivElement"), tetapi juga referensi itu sendiri dan duaHTMLButtonElement
s, yang tidak masuk akal bagi saya. Saya tentu menghargai Anda mengidentifikasi jawaban untuk contoh ini, tetapi saya benar-benar tidak tahu bagaimana menggeneralisasikan ini ke masalah lain.Filter objects allocated between Snapshots 1 and 2 in Snapshot 3's "Summary" view.
artinyaBerikut tip pada profil memori jsfiddle: Gunakan URL berikut untuk mengisolasi hasil jsfiddle Anda, itu menghapus semua kerangka jsfiddle dan memuat hanya hasil Anda.
http://jsfiddle.net/4QhR2/show/
Saya tidak pernah dapat menemukan cara menggunakan Timeline dan Profiler untuk melacak kebocoran memori, sampai saya membaca dokumentasi berikut. Setelah membaca bagian yang berjudul 'Pelacak alokasi objek', saya dapat menggunakan alat 'Rekam Alokasi Tumpukan', dan melacak beberapa node DOM Terpisah.
Saya memperbaiki masalah dengan beralih dari pengikatan acara jQuery, ke menggunakan delegasi acara Backbone. Ini pemahaman saya bahwa versi baru dari Backbone akan secara otomatis melepaskan ikatan acara untuk Anda jika Anda menelepon
View.remove()
. Jalankan beberapa demo sendiri, mereka diatur dengan kebocoran memori untuk Anda identifikasi. Jangan ragu untuk bertanya di sini jika Anda masih belum mendapatkannya setelah mempelajari dokumentasi ini.https://developers.google.com/chrome-developer-tools/docs/javascript-memory-profiling
sumber
Pada dasarnya Anda perlu melihat jumlah objek di dalam snapshot tumpukan Anda. Jika jumlah objek meningkat antara dua foto dan Anda telah membuang objek maka Anda memiliki kebocoran memori. Saran saya adalah untuk mencari penangan acara dalam kode Anda yang tidak terlepas.
sumber
Window/http://jsfiddle.net/4QhR2/show
mungkin bermanfaat, tapi itu hanya fungsi tanpa akhir. Saya tidak tahu apa yang terjadi di sana.Ada video pengantar dari Google, yang akan sangat membantu untuk menemukan kebocoran memori JavaScript.
https://www.youtube.com/watch?v=L3ugr9BJqIs
sumber
Anda juga dapat melihat tab Timeline di alat pengembang. Catat penggunaan aplikasi Anda dan awasi hitungan DOM Node dan pendengar acara.
Jika grafik memori memang mengindikasikan kebocoran memori, maka Anda dapat menggunakan profiler untuk mencari tahu apa yang bocor.
sumber
Anda juga mungkin ingin membaca:
http://addyosmani.com/blog/taming-the-unicorn-easing-javascript-memory-profiling-in-devtools/
Ini menjelaskan penggunaan alat pengembang krom dan memberikan beberapa saran langkah-demi-langkah tentang cara mengonfirmasi dan menemukan kebocoran memori menggunakan heap snapshot perbandingan dan berbagai tampilan snapshot hep yang tersedia.
sumber
Saya kedua saran untuk mengambil snapshot tumpukan, mereka sangat baik untuk mendeteksi kebocoran memori, chrome melakukan pekerjaan snapshotting yang sangat baik.
Dalam proyek penelitian saya untuk gelar saya, saya sedang membangun aplikasi web interaktif yang harus menghasilkan banyak data yang dibangun di 'lapisan', banyak dari lapisan ini akan 'dihapus' di UI tetapi untuk beberapa alasan memori tidak sedang deallocated, menggunakan alat snapshot saya dapat menentukan bahwa JQuery telah menyimpan referensi pada objek (sumbernya adalah ketika saya mencoba untuk memicu suatu
.load()
peristiwa yang menyimpan referensi meskipun keluar dari ruang lingkup). Memiliki informasi ini secara langsung menyelamatkan proyek saya, itu adalah alat yang sangat berguna ketika Anda menggunakan perpustakaan orang lain dan Anda memiliki masalah ini dengan referensi yang tersisa menghentikan GC dari melakukan pekerjaannya.EDIT: Ini juga berguna untuk merencanakan ke depan tindakan apa yang akan Anda lakukan untuk meminimalkan waktu yang dihabiskan untuk snapshotting, berhipotesis apa yang dapat menyebabkan masalah dan uji setiap skenario, buat snapshot sebelum dan sesudah.
sumber
Beberapa catatan penting dalam hal mengidentifikasi kebocoran memori menggunakan alat Pengembang Chrome:
1) Chrome sendiri memiliki kebocoran memori untuk elemen-elemen tertentu seperti kata sandi dan bidang angka. https://bugs.chromium.org/p/chromium/issues/detail?id=967438 . Hindari menggunakan yang saat debugging karena mereka memoles snapshot tumpukan Anda ketika mencari elemen yang terpisah.
2) Hindari mencatat apa pun ke konsol browser. Chrome tidak akan membuang sampah mengumpulkan benda yang ditulis ke konsol, karenanya memengaruhi hasil Anda. Anda dapat menekan output dengan menempatkan kode berikut di awal skrip / halaman Anda:
3) Gunakan heap snapshots dan cari "detach" untuk mengidentifikasi elemen DOM yang terpisah. Dengan mengarahkan objek, Anda mendapatkan akses ke semua properti termasuk id dan outerHTML yang dapat membantu mengidentifikasi setiap elemen. Jika elemen yang terlepas masih terlalu umum untuk dikenali, tetapkan ID unik menggunakan konsol browser sebelum menjalankan tes Anda, misalnya:
Sekarang, ketika Anda mengidentifikasi elemen yang terpisah dengan, katakanlah id = "AutoId_49", muat ulang halaman Anda, jalankan cuplikan di atas lagi, dan temukan elemen dengan id = "AutoId_49" menggunakan inspektur DOM atau document.querySelector (..) . Biasanya ini hanya berfungsi jika konten halaman Anda dapat diprediksi.
Bagaimana saya menjalankan tes saya untuk mengidentifikasi kebocoran memori
1) Muat halaman (dengan output konsol ditekan!)
2) Lakukan hal-hal pada halaman yang dapat menyebabkan kebocoran memori
3) Gunakan Alat Pengembang untuk mengambil snapshot tumpukan dan mencari "lepaskan"
4) Arahkan elemen untuk mengidentifikasi mereka dari properti id atau outerHTML mereka
sumber