اكتشفت عن طريق الخطأ أنه عند تقديم React في الخادم ، عندما يكون Node_env! = الإنتاج ، فإنه سيؤدي إلى تسرب الذاكرة. مشكلات محددة: https://github.com/facebook/react/issues/7406. مع الاستخدام الواسع النطاق للعقدة وتفاعل التماثل والتقنيات الأخرى ، يجب أن تجذب مشكلات مثل تسرب الذاكرة من جانب العقدة انتباهنا. لماذا العقدة عرضة لتسريبات الذاكرة وكيفية استكشاف الأخطاء وإصلاحها بعد حدوثها؟ فيما يلي مقدمة موجزة ومثال.
بادئ ذي بدء ، تعتمد العقدة على محرك V8 ، وطريقة إدارة الذاكرة الخاصة بها تتوافق مع V8. فيما يلي مقدمة موجزة لتأثيرات الذاكرة ذات الصلة لـ V8.
الحد الأقصى للذاكرة V8
تم بناء العقدة على V8 ويمكنها تخصيص وإدارة كائنات JS من خلال V8. V8 لديه قيود على استخدام الذاكرة (حوالي 1.4 جرام للجيل القديم من نظام الذاكرة 64 بت ، حوالي 0.7G للنظام 32 بت ، حوالي 32 ميجابايت للجيل الجديد من نظام الذاكرة 64 بت ، وحوالي 16 ميجابايت لنظام 32 بت). بموجب هذه القيود ، لن تتمكن كائنات الذاكرة الكبيرة من العمل. إذا تم لمس هذه الحدود بطريق الخطأ ، فستخرج العملية.
السبب: يحظر V8 منطق تطبيق JavaScript عند إجراء جمع القمامة ، ثم يعيد تنفيذ منطق تطبيق JavaScript حتى تنتهي مجموعة القمامة. هذا السلوك يسمى "توقف العالم". إذا كانت ذاكرة الكومة لـ V8 هي 1.5 جيجابايت ، فإن الأمر يتطلب أكثر من 50 مللي ثانية لـ V8 للقيام بمجموعة صغيرة من القمامة ، ويستغرق الأمر أكثر من ثانية واحدة لمجموعة القمامة غير المؤرقة.
اضبط ذاكرة الجيل الجديد وذاكرة الجيل القديم لكسر الحد الافتراضي للذاكرة عن طريق تعيين العقدة-حجم الفضاء القديم = xxx (الوحدة MB) و Node-Max-New-Space-Size = xxx (Unit KB).
تكوين كومة V8
لا يتكون كومة V8 بالفعل من جزأين: الجيل القديم والجيل الجديد. يمكن تقسيم الكومة إلى عدة مناطق مختلفة:
نوع إعادة التدوير GC
GC الإضافي
يشير إلى ما إذا كان جامع القمامة يجمع (يضيف) القمامة عند مسح مساحة الذاكرة ويزيل القمامة في نهاية دورة المسح.
GC غير متجانسة
عند استخدام جامع القمامة غير المؤسسي ، تكون القمامة فارغة بمجرد جمعها.
سيقوم جامع القمامة بجمع القمامة فقط لمنطقة ذاكرة الجيل الجديد ومنطقة مؤشر الجيل القديم ومنطقة بيانات الجيل القديم. يدخل الكائن أولاً ذاكرة الجيل الجديد التي تشغل مساحة أقل. ستفشل معظم الكائنات بسرعة ، ويعيد GC غير المؤقتة مباشرة هذه الكميات الصغيرة من الذاكرة. إذا كان لا يمكن إعادة تدوير بعض الكائنات لفترة من الوقت ، فسيتم إدخالها في منطقة ذاكرة الجيل القديم. تنفذ هذه المنطقة GC المتزايد المتكرر ويستغرق وقتًا طويلاً.
ثم متى سيحدث تسرب الذاكرة؟
مسارات تسرب الذاكرة
تركيبة الذاكرة للعقدة هي الجزء الرئيسي المخصص من خلال V8 والجزء الذي تم تخصيصه بواسطة العقدة نفسها. القيد الرئيسي لمجموعة V8's Garbage هو ذاكرة كومة V8. الأسباب الرئيسية لتسرب الذاكرة: 1. ذاكرة التخزين المؤقت ؛ 2. استهلاك قائمة الانتظار ليس في الوقت المناسب ؛ 3. النطاق لم يتم إطلاقه
تحليل تسرب الذاكرة
تحقق من استخدام الذاكرة V8 (وحدة بايت)
process.memoryusage () ؛ {ريس: 47038464 ، heaptotal: 34264656 ، الكومة: 2052866}ريس: جزء الذاكرة المقيمة من العملية
heaptotal ، الكالة: معلومات الذاكرة V8 كومة
تحقق من استخدام ذاكرة النظام (وحدة بايت)
os.totalmem()
OS.Freemem ()
إرجاع إجمالي ذاكرة النظام وذاكرة الخمول
عرض سجل جمع القمامة
العقدة -trace_gc -e "var a = [] ؛ for (var i = 0 ؛ i <1000000 ؛ i ++) {A.Push (صفيف جديد (100)) ؛}" >> GC.LOG // OUTPUT GARBAGE COLLECTION
Node -Prof // الإخراج سجل تنفيذ العقدة. استخدم Windows-tick.processor لعرضها.
أدوات المراقبة التحليلية
يلتقط V8-Profiler لقطات من ذاكرة كومة V8 وتحليل وحدة المعالجة المركزية
العقدة heapdump يمسك لقطات من ذاكرة كومة V8
استخدام مكدس تحليل Node-Mtrace
تستمع عقدة Memwatch إلى وضع جمع القمامة
عقدة memwatch
memwatch.on ('stats' ، function (info) {console.log (info)}) memwatch.on ('Leak' ، function (info) {console.log (info)})حدث الإحصائيات: في كل مرة يتم فيها إجراء مجموعة كاملة من القمامة ، سيتم تشغيل حدث الإحصائيات. هذا الحدث سيمرر إحصائيات الذاكرة.
{"num_full_gc": 17 ، // كم عدد مجموعة القمامة الكاملة "num_inc_gc": 8 ، // كم عدد مجموعة القمامة الإضافية "Heap_Compactions": 8 ، // كم مرة يتم فرز الجيل القديم "reactated_base": 2592568 ، // cardinality "المقدرة": 25925 ، // // // "min": 24999912 ، // minimited "max": 2592568 ، // maximum "use_trend": 0 // user trend}مراقبة num_full_gc و num_inc_gc تعكس مجموعة القمامة.
حدث تسرب: إذا لم يتم إصدار الذاكرة بعد 5 مجموعات على التوالي على التوالي ، فهذا يعني أن تسرب الذاكرة تحدث. هذه المرة سيتم تشغيل حدث تسرب.
{Start: Fri ، 29 Jun 2012 14:12:13 GMT ، End: FRI ، 29 Jun 2012 14:12:33 GMT ، Growth: 67984 ، Qualالكومة DIFFING CHELED مقارنة الذاكرة تقارن استكشاف الأخطاء وإصلاحها رمز التدفق.
أدناه ، نستخدم مثالًا لإظهار كيفية استكشاف تسرب الذاكرة وإصلاحها:
أولاً ننشئ مثالًا يسبب تسرب الذاكرة:
//app.jsvar app = require ('express') () ؛ var http = require ('http'). server (app) ؛ var heapdump = require ('heapdump') ؛ var leakobjs = [] 0 3000) ؛ http.listen (3000 ، function () {console.log ('الاستماع على المنفذ 3000') ؛}) ؛نحن هنا نقوم بمحاكاة تسريبات الذاكرة عن طريق إعداد صفيف يتزايد باستمرار ولا يسترجع.
استخدم وحدة تفريغ الكومة لتسجيل لقطات الذاكرة بانتظام ، واستيراد لقطات من خلال ملفات تعريف أداة مطور Chrome للمقارنة والتحليل.
يمكننا أن نرى أنه بعد الوصول إلى المتصفح المحلي: 3000 ويقوم بتحديثه عدة مرات ، كان حجم اللقطة ينمو ، وحتى إذا لم يتم طلبه ، فإنه لا ينخفض ، مما يشير إلى حدوث تسرب.
ثم نستورد اللقطات من خلال ملفات تعريف أداة مطور Chrome. من خلال إعداد المقارنة ، قارن اللقطة الأولية ، وإرسال الطلبات ، ثم إرسال طلبات لإرسال لقطات الذاكرة في هذه المراحل الثلاث. يمكنك أن تجد أن LeakClass قد تزداد في الجديد على اليمين. دائمًا ما يكون إيجابيًا في دلتا ، فهذا يعني أنه لم يتم إعادة تدويره.
ملخص
بالنسبة لتسربات الذاكرة ، يمكنك استخدام Memwatch لزرع ، أو الإبلاغ عن العملية.
عند العثور على تسرب الذاكرة ، إذا سمحت ، يمكنك تشغيل عقدة Heapdump محليًا واستخدام لقطات الذاكرة المحددة لتوليدها. واستخدم اللقطة لتحليل سبب التسرب من خلال ملفات تعريف الكروم. إذا لم يكن التصحيح المحلي ممكنًا ، فاستخدم V8-Profiler لإخراج لقطات الذاكرة على خادم الاختبار لمقارنة وتحليل JSON (مطلوب اقتحام الكود).
تحت أي ظروف ينبغي النظر فيها ، يتم تمكين Memwatch/Heapdump. النظر في تواتر heapdump لتجنب نفاد وحدة المعالجة المركزية. يمكن أيضًا النظر في طرق أخرى للكشف عن نمو الذاكرة ، مثل عملية المراقبة مباشرة. الذاكرة ().
احذر من سوء الحكم ، تتصرف قمم استخدام الذاكرة على المدى القصير مثل تسرب الذاكرة. إذا كان تطبيقك يستهلك فجأة الكثير من وحدة المعالجة المركزية والذاكرة ، فقد يمتد وقت المعالجة عدة دورات لجمع القمامة ، ثم قد يسيطر Memwatch على إساءة تقديرها لتسرب الذاكرة. ومع ذلك ، في هذه الحالة ، بمجرد أن يستخدم تطبيقك هذه الموارد ، سيعود استهلاك الذاكرة إلى المستويات العادية. لذلك من المهم أن نلاحظ أنه يتم الإبلاغ عن تسرب الذاكرة بشكل مستمر ، ويمكن تجاهل واحد أو اثنين من الإنذارات المفاجئة.