Saya secara tidak sengaja menemukan bahwa ketika bereaksi diterjemahkan di server, ketika node_env! = Produksi, itu akan menyebabkan kebocoran memori. Masalah khusus: https://github.com/facebook/react/issues/7406. Dengan penggunaan node dan reaksi isomorfisme dan teknologi lainnya secara luas, masalah-masalah seperti kebocoran memori sisi simpul harus menarik perhatian kita. Mengapa simpul rentan terhadap kebocoran memori dan bagaimana cara memecahkan masalah setelah itu terjadi? Berikut ini adalah pengantar dan contoh singkat.
Pertama -tama, Node didasarkan pada mesin V8, dan metode manajemen memorinya konsisten dengan V8. Berikut ini adalah pengantar singkat tentang efek memori yang relevan dari V8.
Batas memori V8
Node dibangun di atas V8 dan dapat mengalokasikan dan mengelola objek JS melalui V8. V8 memiliki keterbatasan penggunaan memori (sekitar 1,4g untuk generasi lama sistem memori 64-bit, sekitar 0,7g untuk sistem 32-bit, sekitar 32MB untuk generasi baru sistem memori 64-bit, dan sekitar 16MB untuk sistem 32-bit). Di bawah batasan seperti itu, objek memori besar tidak akan dapat beroperasi. Jika batas ini disentuh secara tidak sengaja, prosesnya akan keluar.
Penyebab: V8 memblokir logika aplikasi JavaScript saat melakukan pengumpulan sampah, dan kemudian eksekusi ulang logika aplikasi JavaScript sampai pengumpulan sampah selesai. Perilaku ini disebut "stop-the-world". Jika heap memori V8 adalah 1,5GB, dibutuhkan lebih dari 50 ms untuk V8 untuk melakukan koleksi sampah kecil, dan dibutuhkan lebih dari 1 detik untuk koleksi sampah non-Incremental.
Atur memori generasi baru dan memori generasi lama untuk memecahkan batas memori default dengan mengatur simpul --max-space-size = xxx (unit mb) dan node--max-new-space-size = xxx (unit kb).
Komposisi Heap V8
Tumpukan V8 sebenarnya tidak terdiri dari dua bagian: generasi lama dan generasi baru. Tumpukan dapat dibagi menjadi beberapa daerah yang berbeda:
Jenis Daur Ulang GC
GC tambahan
Menunjukkan apakah pengumpul sampah mengumpulkan (menambahkan) sampah saat memindai ruang memori dan membersihkan sampah di akhir siklus pemindaian.
GC non-Incremental
Saat menggunakan kolektor sampah non-Incremental, sampah kosong segera setelah dikumpulkan.
Pengumpul sampah hanya akan melakukan pengumpulan sampah untuk area memori generasi baru, area pointer generasi lama dan area data generasi lama. Objek pertama kali memasuki memori generasi baru yang membutuhkan lebih sedikit ruang. Sebagian besar objek akan gagal dengan cepat, dan GC non-intremental secara langsung mendaur ulang sejumlah kecil memori ini. Jika beberapa objek tidak dapat didaur ulang untuk jangka waktu tertentu, mereka akan dimasukkan ke dalam area memori generasi lama. Area ini mengeksekusi GC inkremental yang jarang dan membutuhkan waktu lama.
Lalu kapan bocor memori akan terjadi?
Jalur bocor memori
Komposisi memori node terutama adalah bagian yang dialokasikan melalui V8 dan bagian yang dialokasikan oleh simpul itu sendiri. Keterbatasan utama koleksi sampah V8 adalah heap memori V8. Alasan utama kebocoran memori: 1. Cache; 2. Konsumsi antrian tidak tepat waktu; 3. Lingkup tidak dirilis
Analisis Kebocoran Memori
Periksa penggunaan memori V8 (unit byte)
Process.MemoryUsage (); {ress: 47038464, heeptotal: 34264656, heapused: 2052866}Ress: bagian memori residen dari proses
heeptotal, heapuse: v8 informasi memori heap
Periksa penggunaan memori sistem (unit byte)
os.totalmem()
os.freemem ()
Mengembalikan memori sistem total dan memori idle
Lihat Log Koleksi Sampah
node --trace_gc -e "var a = []; untuk (var i = 0; i <1000000; i ++) {A.push (array baru (100));}" >> gc.log // log koleksi output koleksi sampah output
Node --prof // Output Node Eksekusi Kinerja Log. Gunakan windows-tick.processor untuk melihat.
Alat pemantauan analitik
V8-Profiler menangkap snapshot dari v8 heap memori dan menganalisis CPU
Node-heapdump mengambil snapshot dari v8 heap memori
Penggunaan Stack Analisis Node-Mtrace
Node-Memwatch mendengarkan situasi pengumpulan sampah
Node-Memwatch
memwatch.on ('stats', function (info) {console.log (info)}) memwatch.on ('bocor', function (info) {console.log (info)}))Acara Stats: Setiap kali koleksi sampah penuh dilakukan, acara statistik akan dipicu. Acara ini akan melewati statistik memori.
{"num_full_gc": 17, //How many full-stack garbage collection "num_inc_gc": 8, //How many incremental garbage collection "heap_compactions": 8, //How many times the old generation are sorted out "estimated_base": 2592568, //The estimated cardinality "current_base": 2592568, //The current cardinality "min": 249912, // minimum "max": 2592568, // maksimum "usage_trend": 0 // tren pengguna}Amati num_full_gc dan num_inc_gc memantulkan koleksi sampah.
Acara Kebocoran: Jika memori masih belum dirilis setelah 5 koleksi sampah berturut -turut, itu berarti kebocoran memori terjadi. Kali ini acara kebocoran akan dipicu.
{Start: Fri, 29 Jun 2012 14:12:13 GMT, Akhir: Fri, 29 Jun 2012 14:12:33 GMT, Pertumbuhan: 67984, Alasan: 'Tumpukan pertumbuhan lebih dari 5 GC berturut -turut (20 -an) - 11.67 MB/jam'}Heap Diffing Heap Memoron Perbandingan Memecahkan Masalah memori overflow Code.
Di bawah ini, kami menggunakan contoh untuk menunjukkan cara memecahkan masalah memori:
Pertama kami membuat contoh yang menyebabkan kebocoran memori:
//app.jsvar app = membutuhkan ('express') (); var http = membutuhkan ('http'). server (app); var heapdump = membutuhkan ('heapdump'); var leakoBjs = []; for for {rese) {this.x = 1;} app.get ('', req, req, {this. 0; 3000); http.listen (3000, function () {console.log ('Mendengarkan pada port 3000');});Di sini kami mensimulasikan kebocoran memori dengan menyiapkan array yang terus meningkat dan tidak mengambil.
Gunakan modul heap-dump untuk merekam snapshot memori secara teratur, dan impor snapshot melalui profil alat pengembang chrome untuk perbandingan dan analisis.
Kita dapat melihat bahwa setelah browser mengakses localhost: 3000 dan menyegarkannya berkali -kali, ukuran snapshot telah tumbuh, dan bahkan jika tidak diminta, itu tidak berkurang, menunjukkan bahwa kebocoran telah terjadi.
Kemudian kami mengimpor snapshot melalui profil alat pengembang Chrome. Dengan mengatur perbandingan, bandingkan snapshot awal, kirim permintaan, dan kemudian kirim permintaan untuk mengirim snapshot memori dalam tiga tahap ini. Anda dapat menemukan bahwa LeakClass telah meningkat di yang baru di sebelah kanan. Selalu positif di Delta, itu berarti belum didaur ulang.
ringkasan
Untuk kebocoran memori, Anda dapat menggunakan Memwatch untuk menanamkan, atau melaporkan prosesnya. Penggunaan memori USUMNYA untuk memantau secara teratur, dan mengatur ambang batas alarm untuk pemantauan.
Ketika kebocoran memori ditemukan, jika diizinkan, Anda dapat menjalankan node-heapdump secara lokal dan menggunakan snapshot memori waktunya untuk dihasilkan. Dan gunakan snapshot untuk menganalisis penyebab kebocoran melalui profil krom. Jika debugging lokal tidak dimungkinkan, gunakan V8-profiler untuk mengeluarkan snapshot memori pada server uji untuk membandingkan dan menganalisis JSON (diperlukan intrusi kode).
Dalam keadaan apa harus dipertimbangkan, Memwatch/HeapDump diaktifkan. Pertimbangkan frekuensi Heapdump untuk menghindari kehabisan CPU. Cara lain untuk mendeteksi pertumbuhan memori juga dapat dipertimbangkan, seperti proses pemantauan langsung. MEMORYUSAGE ().
Waspadalah terhadap kesalahan penilaian, puncak penggunaan memori jangka pendek berperilaku seperti kebocoran memori. Jika aplikasi Anda tiba -tiba mengonsumsi banyak CPU dan memori, waktu pemrosesan dapat menjangkau beberapa siklus pengumpulan sampah, dan kemudian Memwatch dapat salah menilai sebagai kebocoran memori. Namun, dalam hal ini, setelah aplikasi Anda menggunakan sumber daya ini, konsumsi memori akan turun kembali ke tingkat normal. Jadi penting untuk dicatat bahwa kebocoran memori terus dilaporkan, dan satu atau dua alarm mendadak dapat diabaikan.