تعرَّف على كيفية استخدام Chrome وDevTools للعثور على مشاكل الذاكرة التي تؤثّر في أداء الصفحة، بما في ذلك تسرُّب الذاكرة وتضخّم الذاكرة وعمليات جمع المهملات المتكرّرة.
ملخّص
- يمكنك معرفة مقدار الذاكرة التي تستخدمها صفحتك باستخدام ميزة "إدارة المهام" في Chrome.
- عرض استخدام الذاكرة بمرور الوقت من خلال تسجيلات "المخطّط الزمني"
- يمكنك تحديد أشجار نموذج عناصر في المستند (DOM) المنفصلة (وهي سبب شائع لتسرُّب الذاكرة) باستخدام "لقطات Heap".
- يمكنك معرفة وقت تخصيص ذاكرة جديدة في حزمة JS باستخدام تسجيلات "مخطّط تخصيص الذاكرة".
- تحديد العناصر المنفصلة التي يحتفظ بها مرجع JavaScript
نظرة عامة
وفقًا لنموذج الأداء RAIL، يجب أن تركّز جهودك المبذولة لتحسين الأداء على المستخدمين.
إنّ مشاكل الذاكرة مهمة لأنّ المستخدمين يميزونها في أغلب الأحيان. يمكن للمستخدمين ملاحظة مشاكل في الذاكرة بالطُرق التالية:
- يزداد سوء أداء الصفحة تدريجيًا بمرور الوقت: قد يكون هذا ناتجًا عن تسرُّب قيد الذاكرة. يحدث تسرُّب الذاكرة عندما يؤدي خطأ في الصفحة إلى استخدامها بشكلٍ متزايد ومتزايد مع مرور الوقت.
- أداء الصفحة سيئ بشكلٍ ثابت: قد يشير ذلك إلى أنّ ذاكرة الجهاز ممتلئة. يحدث "تضخم الذاكرة" عندما تستخدم الصفحة ذاكرة أكثر من اللازم لضمان سرعة الصفحة المثلى.
- تأخّر أداء الصفحة أو يبدو أنّه يتوقّف مؤقتًا بشكل متكرّر. قد يكون هذا أحد أعراض عمليات جمع المهملات المتكرّرة. جمع المهملات هو عندما يستردّ المتصفّح الذاكرة. ويحدِّد المتصفّح متى يحدث ذلك. أثناء عمليات جمع البيانات، يتم إيقاف تنفيذ جميع النصوص البرمجية مؤقتًا. وبالتالي، إذا كان المتصفّح يجمع الكثير من الملفات غير الصالحة، سيتم إيقاف تنفيذ النصوص البرمجية مؤقتًا كثيرًا.
تضخم الذاكرة: ما هو الحدّ الأقصى المسموح به؟
من السهل تحديد تسرُّب الذاكرة. إذا كان أحد المواقع الإلكترونية يستخدم بشكل تدريجي المزيد والمزيد من الذاكرة، يعني ذلك أنّه يواجه تسرُّبًا. ولكن من الصعب تحديد سبب تضخم الذاكرة. ما هي الحالات التي تُعدّ فيها التطبيقات "تستهلك مساحة كبيرة جدًا من الذاكرة"؟
لا تتوفّر أرقام محددة هنا، لأنّ الأجهزة والمتصفحات المختلفة تتمتع بإمكانات مختلفة. قد تتعطل الصفحة نفسها التي تعمل بسلاسة على هاتف ذكي فائق الأداء على هاتف ذكي منخفض الأداء.
يكمن المفتاح هنا في استخدام نموذج RAIL والتركيز على المستخدمين. تعرَّف على الأجهزة الشائعة لدى المستخدمين، ثم اختبِر صفحتك على تلك الأجهزة. إذا كانت التجربة باستمرار سيئة، قد تكون الصفحة تتجاوز قدرات الذاكرة على هذه الأجهزة.
مراقبة استخدام الذاكرة في الوقت الفعلي باستخدام "إدارة مهام Chrome"
استخدِم "إدارة المهام" في Chrome كنقطة بداية للتحقيق في مشكلة الذاكرة. "إدارة المهام" هي أداة مراقبة في الوقت الفعلي تُعلمك بكمية الذاكرة التي تستخدمها الصفحة.
اضغط على Shift+Esc أو انتقِل إلى القائمة الرئيسية في Chrome واختَر المزيد من الأدوات > إدارة المهام لفتح "إدارة المهام".
انقر بزر الماوس الأيمن على عنوان الجدول في "مدير المهام" وفعِّل ذاكرة JavaScript.
يوضّح لك هذان العمودان معلومات مختلفة عن كيفية استخدام صفحتك للذاكرة:
- يمثّل عمود استهلاك الذاكرة ذاكرة نظام التشغيل. يتم تخزين عُقد DOM في ذاكرة نظام التشغيل. إذا كانت هذه القيمة في تزايد، يعني ذلك أنّه يتم إنشاء عقد DOM.
يمثّل عمود ذاكرة JavaScript كومة الذاكرة المؤقتة لجافا سكريبت. يحتوي هذا العمود على قيمتَين. قيمة المطلوبة هي الرقم المباشر (الرقم بين قوسين). يمثّل الرقم المباشر حجم الذاكرة التي تستخدمها العناصر التي يمكن الوصول إليها على صفحتك. إذا كان هذا الرقم في تزايد، يعني ذلك أنّه يتم إنشاء عناصر جديدة أو أنّ عدد العناصر الحالية في تزايد.
عرض عمليات تسرُّب الذاكرة باستخدام تسجيلات الأداء
يمكنك أيضًا استخدام لوحة الأداء كنقطة بداية أخرى في التحقيق. تساعدك لوحة "الأداء" في الاطّلاع على استخدام الذاكرة للصفحة بمرور الوقت.
- افتح لوحة الأداء في "أدوات مطوّري البرامج".
- فعِّل مربّع الاختيار الذاكرة.
- إنشاء تسجيل
لتوضيح تسجيلات ذاكرة الأداء، راجِع الرمز البرمجي التالي:
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);
في كل مرة يتم فيها الضغط على الزر المُشار إليه في الرمز، تتم إضافة عشرة آلاف عقدة div
إلى نص المستند، ويتم دفع سلسلة من مليون حرف x
إلى صفيف x
.
يؤدي تشغيل هذا الرمز البرمجي إلى إنشاء تسجيل للمخطط الزمني مثل لقطة الشاشة التالية:
أولاً، شرح واجهة المستخدم يمثّل الرسم البياني HEAP في لوحة نظرة عامة (أسفل NET) ذاكرة JavaScript المحجوزة. أسفل لوحة نظرة عامة، تظهر لوحة العداد. يمكنك هنا الاطّلاع على استخدام الذاكرة مقسّمًا حسب كومة الذاكرة المؤقتة لجافا سكريبت (كما هو الحال في الرسم البياني HEAP في لوحة نظرة عامة)، والمستندات وعقد DOM والمستمعين وذاكرة وحدة معالجة الرسومات. يؤدي إيقاف مربّع اختيار إلى إخفائه من الرسم البياني.
الآن، تحليل للرمز مقارنةً بلقطة الشاشة. إذا اطّلعت على عداد العقد (الرسم البياني
الأخضر)، يمكنك ملاحظة أنّه يتطابق بدقة مع الرمز. يزداد عدد العقد في
خطوات منفصلة. يمكنك افتراض أنّ كل زيادة في عدد العقد هي طلب إلى grow()
. لا يكون رسم بياني "قمامة JavaScript" (الرسم البياني الأزرق) مباشرًا. وفقًا لأفضل الممارسات، فإنّ الانخفاض الأول
هو في الواقع عملية جمع غير مرغوب فيها للعناصر غير الضرورية (يتم إجراؤها من خلال الضغط على الزر جمع العناصر غير الضرورية). مع
تقدّم التسجيل، يمكنك ملاحظة ارتفاع حجم العناصر المتعدّدة في رمز JavaScript. وهذا أمر طبيعي ومتوقّع: يعمل رمز JavaScript على إنشاء عقد DOM عند كل نقرة على الزر ويُجري الكثير من العمل عند
إنشاء سلسلة من مليون حرف. إنّ النقطة الأساسية هنا هي أنّ ذاكرة تخزين JavaScript تنتهي
بقيمة أعلى من قيمتها عند البدء (تكون "البداية" هنا هي النقطة التي تلي عملية جمع المهملات القسري). في
الواقع، إذا لاحظت هذا النمط من زيادة حجم ذاكرة التخزين المؤقت لـ JavaScript أو حجم العقدة، قد يشير ذلك
إلى تسرُّب للذاكرة.
اكتشاف حالات تسرُّب الذاكرة في شجرة نموذج العناصر في المستند المنفصلة باستخدام "لقطات Heap"
لا يمكن جمع المهملات لعقدة DOM إلا عندما لا تتوفّر أيّ إشارات إليها من شجرة DOM للصفحة أو رمز JavaScript. يُقال أنّ إحدى العقد "مُفصَلة" عندما تتم إزالتها من شجرة نموذج DOM، ولكن لا تزال بعض وحدات JavaScript تشير إليها. إنّ عُقد DOM المنفصلة هي سبب شائع لتسرُّب الذاكرة. يوضّح لك هذا القسم كيفية استخدام أدوات تحليل الذاكرة في أدوات مطوّري البرامج لتحديد العقد غير المُدرَجة.
في ما يلي مثال بسيط على عقد DOM غير المرتبطة.
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);
يؤدي النقر على الزر المُشار إليه في الرمز إلى إنشاء عقدة ul
تحتوي على عشرة عناصر فرعية من النوع li
. تتم الإشارة إلى هذه العقد
من خلال الرمز البرمجي، ولكنها لا تظهر في شجرة DOM، لذا يتم فصلها.
لقطات الذاكرة العشوائية هي إحدى الطرق لتحديد العقد غير المُدرَجة. كما يشير الاسم، تعرض لك لقطات الذاكرة المتعدّدة كيفية توزيع الذاكرة بين كائنات JavaScript وعُقَد DOM في صفحتك في وقت التقاط اللقطة.
لإنشاء لقطة، افتح "أدوات المطوّر" وانتقِل إلى لوحة الذاكرة، ثم اختَر زر الاختيار لقطة ذاكرة عشوائية، ثم اضغط على الزر أخذ لقطة.
قد يستغرق تحميل اللقطة ومعالجتها بعض الوقت. بعد اكتمال العملية، اختَر التحليل من اللوحة اليمنى (المعروف باسم لقطات Heap).
اكتب Detached
في مربّع إدخال فلتر الفئة للبحث عن أشجار DOM غير المُدرَجة.
وسِّع العلامات التجارية للتحقيق في شجرة منفصلة.
انقر على عقدة للتحقيق فيها بشكل أكبر. في لوحة العناصر، يمكنك الاطّلاع على مزيد من
المعلومات عن الرمز الذي يشير إليه. على سبيل المثال، في لقطة الشاشة التالية، يمكنك الاطّلاع على
أنّ المتغيّر detachedTree
يشير إلى العقدة. لحلّ مشكلة تسرُّب الذاكرة هذه، عليك
دراسة الرمز الذي يستخدم detachedTree
والتأكّد من أنّه يزيل الإشارة إلى العقدة
عندما لا تكون مطلوبة.
تحديد حالات تسرُّب ذاكرة عناصر JavaScript المتعدّدة باستخدام "المخططات الزمنية لتخصيص أجزاء من الذاكرة"
مخطط تخصيص الذاكرة هو أداة أخرى يمكن أن تساعدك في تتبُّع تسرُّب الذاكرة في حِزمة JavaScript.
لتوضيح مخطط توزيع المساحة، راجِع الرمز البرمجي التالي:
var x = [];
function grow() {
x.push(new Array(1000000).join('x'));
}
document.getElementById('grow').addEventListener('click', grow);
في كل مرة يتم فيها الضغط على الزر المُشار إليه في الرمز، تتم
إضافة سلسلة من مليون حرف إلى مصفوفة x
.
لتسجيل مخطط زمني للمساحة المخصّصة، افتح "أدوات المطوّر"، وانتقِل إلى لوحة الذاكرة، وانقر على زر الاختيار عمليات التخصيص على المخطط الزمني، واضغط على الزر
تسجيل، ثم نفِّذ الإجراء الذي تعتقد أنّه يتسبب في تسرُّب الذاكرة، ثم اضغط على الزر إيقاف التسجيل عند الانتهاء.أثناء التسجيل، لاحظ ما إذا كان أيّ أشرطة زرقاء تظهر في مخطّط زمني للتوزيع، كما هو موضّح في لقطة الشاشة التالية.
تمثّل هذه الأشرطة الزرقاء عمليات تخصيص الذاكرة الجديدة. إنّ عمليات تخصيص الذاكرة الجديدة هذه هي المرشحة لاكتشاف تسرُّب الذاكرة. يمكنك تكبير شريط لفلترة لوحة المنشئ لعرض العناصر التي تم تخصيصها خلال الإطار الزمني المحدّد فقط.
وسِّع العنصر وانقر على قيمته للاطّلاع على مزيد من التفاصيل عنه في لوحة العنصر. على سبيل المثال، في لقطة الشاشة أدناه، من خلال عرض تفاصيل العنصر الذي تم تخصيصه حديثًا،
يمكنك الاطّلاع على أنّه تم تخصيصه للمتغيّر x
في نطاق Window
.
التحقيق في تخصيص الذاكرة حسب الدالة
استخدِم نوع الملفّ التعريفي تحليل عيّنات التخصيص في لوحة الذاكرة لعرض تخصيص الذاكرة حسب وظيفة JavaScript.
- انقر على زر الاختيار تحليل عيّنات التوزيع. إذا كان هناك عامل في الصفحة، يمكنك اختياره كهدف لإنشاء الملف الشخصي من نافذة اختيار مثيل جهاز افتراضي لبرنامج JavaScript.
- اضغط على زر بدء.
- نفِّذ الإجراءات على الصفحة التي تريد التحقيق فيها.
- اضغط على الزر إيقاف عند الانتهاء من جميع الإجراءات.
تعرِض لك أدوات المطوّرين تفاصيل تخصيص الذاكرة حسب الدالة. العرض التلقائي هو الوظائف ذات الاستخدام المكثّف للذاكرة (من الأسفل للأعلى)، والذي يعرض الدوالّ التي خصصت أكبر قدر من الذاكرة في أعلى الصفحة.
تحديد الكائنات التي يحتفظ بها مرجع JS
يعرض لك الملف الشخصي العناصر المنفصلة العناصر المنفصلة التي تبقى ظاهرة لأنّ رمز JavaScript يشير إليها.
سجِّل ملفًا شخصيًا للعناصر غير المضمّنة لعرض عدد عقد HTML وعدد العقد بالضبط.
تحديد مواعيد جمع القمامة المتكرّرة
إذا كانت صفحتك تتوقف مؤقتًا بشكل متكرّر، قد تكون هناك مشاكل في جمع المهملات.
يمكنك استخدام ميزة "إدارة المهام" في Chrome أو تسجيلات ذاكرة "المخطّط الزمني" لرصد عمليات جمع القمامة المتكررة. في "مدير المهام"، تشير القيم المتصاعدة أو الهابطة بشكل متكرر في الذاكرة أو ذاكرة JavaScript إلى عمليات جمع المهملات المتكررة. في تسجيلات "المخطط الزمني"، تشير الرسوم البيانية المتصاعدة أو الهابطة لحجم ذاكرة التخزين المؤقت أو عدد العقد في JavaScript إلى عمليات جمع المهملات المتكررة.
بعد تحديد المشكلة، يمكنك استخدام تسجيل "مخطط تخصيص الذاكرة" لمعرفة مكان تخصيص الذاكرة والدوالّ التي تؤدي إلى عمليات التخصيص.