تسجيل لقطات مجمّعة

Meggin Kearney
Meggin Kearney
Sofia Emelianova
Sofia Emelianova

تعرَّف على كيفية تسجيل لقطات للعناصر المتعدّدة باستخدام الذاكرة > الملفات التعريفية > لقطة للعناصر المتعدّدة والعثور على عمليات تسرُّب الذاكرة.

يعرض أداة تحليل الذاكرة توزيع الذاكرة حسب كائنات JavaScript في صفحتك وعُقَد DOM ذات الصلة. ويمكنك استخدام هذه الأداة لأخذ لقطات لأجزاء من الذاكرة في JavaScript وتحليل الرسوم البيانية للذاكرة ومقارنة اللقطات والعثور على تسرُّب الذاكرة. لمزيد من المعلومات، يُرجى الاطّلاع على شجرة الاحتفاظ بالعناصر.

التقاط لقطة

لالتقاط لقطة لعناصر متعدّدة:

  1. في الصفحة التي تريد إنشاء ملف شخصي لها، افتح أدوات مطوّري البرامج وانتقِل إلى لوحة الذاكرة.
  2. اختَر نوع ملف لقطة ذاكرة عشوائية، ثم اختَر مثيل جهاز افتراضي لبرنامج JavaScript، وانقر على التقاط لقطة.

نوع ملف تعريف محدّد ومثيل جهاز افتراضي لبرنامج JavaScript

عندما يتم تحميل اللقطة وتحليلها في لوحة الذاكرة، يتم عرض الحجم الإجمالي لكائنات JavaScript التي يمكن الوصول إليها أسفل عنوان اللقطة في قسم لقطات لقطات الشاشة (HEAP).

الحجم الإجمالي للعناصر التي يمكن الوصول إليها

لا تعرض اللقطات سوى العناصر من الرسم البياني للذاكرة التي يمكن الوصول إليها من الكائن الشامل. تبدأ عملية التقاط لقطة احتياطية دائمًا بجمع الملفات غير الضرورية.

لقطة شاشة للكومة من عناصر Item المتفرقة

محو اللقطات

لإزالة جميع اللقطات، انقر على محو جميع الملفات التعريفية:

محو جميع الملفات الشخصية

عرض اللقطات

لفحص اللقطات من وجهات نظر مختلفة لأغراض مختلفة، اختَر أحد طرق العرض من القائمة المنسدلة في أعلى الصفحة:

عرض المحتوى الغرض
ملخّص الكائنات المجمّعة حسب أسماء الدوالّ الإنشائية استخدِم هذا التقرير للعثور على العناصر ومعرفة مقدار استخدامها للذاكرة استنادًا إلى النوع. مفيدة لتتبُّع عمليات تسرُّب DOM
المقارنة الاختلافات بين لقطتين. ويمكنك استخدام هذه الميزة لمقارنة لقطتين (أو أكثر) قبل العملية وبعدها. تأكَّد من تسرُّب الذاكرة وسببه من خلال فحص الفرق في الذاكرة المُستغَلة وعدد الإشارات.
الاحتواء محتويات الحِزم يوفّر عرضًا أفضل لبنية العنصر، ويساعد في تحليل العناصر المُشار إليها في مساحة الاسم العالمية (النافذة) للعثور على ما يبقيها ظاهرة. ويمكنك استخدامه لتحليل حالات الإغلاق والتعمق في العناصر عند مستوى منخفض.
الإحصاءات رسم بياني دائري لتخصيص الذاكرة اطّلِع على الأحجام النسبية لأجزاء الذاكرة المخصّصة للرمز البرمجي والسلاسل وصفائف JavaScript وصفائف النصوص البرمجية لكائنات النظام.

عرض "الملخّص" الذي تم اختياره من القائمة المنسدلة في أعلى الصفحة

العرض الملخّص

في البداية، يتم فتح لقطة ذاكرة عشوائية في طريقة عرض الملخّص التي تسرد العناصر المنشئة في عمود. يمكنك توسيع وظائف الإنشاء للاطّلاع على العناصر التي تم إنشاؤها.

عرض "الملخّص" مع أداة إنشاء موسّعة

لفلترة دوال الإنشاء غير الملائمة، اكتب اسمًا تريد فحصه في فلتر الفئة في أعلى طريقة عرض الملخّص.

تشير الأرقام بجانب أسماء الدوالّ الإنشائية إلى إجمالي عدد العناصر التي تم إنشاؤها باستخدام الدالة الإنشائية. تعرِض طريقة العرض الملخّص أيضًا الأعمدة التالية:

  • تعرِض المسافة المسافة إلى الجذر باستخدام أقصر مسار بسيط للعقد.
  • تعرِض سمة الحجم البسيط مجموع الأحجام البسيطة لجميع العناصر التي أنشأها أسلوب إنشاء معيّن. الحجم الصغير هو حجم الذاكرة التي يحتفظ بها العنصر نفسه. بشكل عام، تكون أحجام الصفائف والسلاسل أكبر. اطّلِع أيضًا على أحجام الكائنات.
  • يعرض الحجم الذي تم الاحتفاظ به الحد الأقصى للحجم الذي تم الاحتفاظ به بين مجموعة العناصر نفسها. الحجم المحفوظ هو حجم الذاكرة الذي يمكنك تحريره من خلال حذف عنصر ومنع الوصول إلى العناصر التي تعتمد عليه. اطّلِع أيضًا على أحجام الكائنات.

عند توسيع عنصر إنشاء، يعرض لك عرض الملخّص جميع نُسخه. تحصل كلّ نسخة على تفاصيل عن أحجامها السطحية والمحفوظة في الأعمدة المقابلة. الرقم الذي يلي الحرف @ هو المعرّف الفريد للعنصر. يتيح لك ذلك مقارنة لقطات الذاكرة المؤقتة على أساس كل عنصر.

فلاتر الشركات المصنّعة

يتيح لك عرض الملخّص فلترة منشئي البنى استنادًا إلى الحالات الشائعة لاستخدام الذاكرة غير الفعّال.

لاستخدام هذه الفلاتر، حدد أحد الخيارات التالية من القائمة المنسدلة في أقصى اليسار في شريط الإجراءات:

  • جميع الكائنات: جميع الكائنات التي التقطتها اللقطة الحالية يتم ضبطه تلقائيًا.
  • العناصر التي تم تخصيصها قبل اللقطة 1: العناصر التي تم إنشاؤها وظلّت في الذاكرة قبل التقاط اللقطة الأولى.
  • العناصر التي تم تخصيصها بين اللقطتَين 1 و2: يمكنك الاطّلاع على الفرق في العناصر بين اللقطة الأخيرة واللقطة السابقة. تضيف كل لقطة جديدة جزءًا من هذا الفلتر إلى القائمة المنسدلة.
  • السلاسل المكرّرة: قيم السلاسل التي تم تخزينها عدة مرات في الذاكرة
  • الكائنات التي تحتفظ بها العقد المنفصلة: الكائنات التي يتم الاحتفاظ بها لأنّ عقدة DOM منفصلة تشير إليها.
  • الكائنات التي تحتفظ بها وحدة تحكّم أدوات مطوّري البرامج: الكائنات التي يتم الاحتفاظ بها في الذاكرة لأنّه تم تقييمها أو التفاعل معها من خلال وحدة تحكّم أدوات مطوّري البرامج.

الإدخالات الخاصة في "الملخّص"

بالإضافة إلى التجميع حسب منشئي الوظائف، يُجمِّع عرض الملخّص أيضًا الكائنات حسب:

  • الدوالّ المدمَجة، مثل Array أو Object
  • عناصر HTML مجمّعة حسب علاماتها، مثل <div> و<a> و<img> وغيرها
  • الدوال التي حدّدتها في التعليمات البرمجية
  • الفئات الخاصة التي لا تستند إلى الدوال الإنشائية.

إدخالات المُنشئ

(array)

تتضمّن هذه الفئة كائنات داخلية مختلفة تشبه المصفوفات ولا تتطابق مباشرةً مع الكائنات الظاهرة في JavaScript.

على سبيل المثال، يتم تخزين محتوى كائنات Array في JavaScript في كائن داخلي ثانوي يُسمى (object elements)[]، للسماح بتغيير حجمها بسهولة أكبر. وبالمثل، يتم غالبًا تخزين السمات المحدّدة في عناصر JavaScript في كائنات داخلية ثانوية تُسمّى (object properties)[] ومدرَجة أيضًا في الفئة (array).

(compiled code)

تتضمّن هذه الفئة البيانات الداخلية التي يحتاجها V8 لكي يتمكّن من تنفيذ الدوالّ المحدّدة باستخدام JavaScript أو WebAssembly. يمكن تمثيل كل وظيفة بطرق متنوعة، بدءًا من الوظيفة الصغيرة والبطيئة ووصولاً إلى الوظيفة الكبيرة والسريعة.

يدير V8 استخدام الذاكرة تلقائيًا في هذه الفئة. إذا تم تشغيل دالة عدة مرات، يستخدم V8 المزيد من الذاكرة لهذه الدالة حتى يمكن تشغيلها بشكل أسرع. إذا لم يتم تشغيل دالة منذ فترة، قد يمحو V8 البيانات الداخلية لتلك الدالة.

(concatenated string)

عندما يربط V8 سلسلتَين، كما هو الحال مع عامل تشغيل JavaScript +، قد يختار تمثيل النتيجة داخليًا على أنّها "سلسلة تسلسلية" تُعرف أيضًا باسم بنية بيانات Rope.

بدلاً من نسخ جميع أحرف السلسلتَين المصدرَين إلى سلسلة جديدة، يخصِّص V8 عنصرًا صغيرًا يحتوي على حقلَين داخليَين باسم first وsecond، ويشيران إلى سلسلتَي المصدر. ويتيح ذلك لـ V8 توفير الوقت والذاكرة. من منظور رمز JavaScript، هذه مجرد سلاسل عادية، وتتصرف مثل أي سلسلة أخرى.

InternalNode

تمثّل هذه الفئة العناصر المخصّصة خارج V8، مثل كائنات C++‎ المحدَّدة باستخدام Blink.

للاطّلاع على أسماء فئات C++، استخدِم Chrome للاختبار واتّبِع الخطوات التالية:

  1. افتح "أدوات مطوري البرامج" وفعِّل الإعدادات > التجارب > إظهار الخيار لعرض العناصر الداخلية في لقطات لأجزاء من الذاكرة.
  2. افتح لوحة الذاكرة، واختَر لقطة لأجزاء من الذاكرة، ثم فعِّل عرض الإعدادات الداخلية (يتضمّن تفاصيل إضافية خاصة بعملية التنفيذ).
  3. أعِد تنفيذ الخطوات التي أدّت إلى احتفاظ InternalNode بالكثير من الذاكرة.
  4. احصل على لقطة لعناصر متعدّدة. في هذه اللقطة، تحتوي العناصر على أسماء فئات C++ بدلاً من InternalNode.
(object shape)

كما هو موضّح في السمات السريعة في V8، يتتبّع V8 الفئات المخفية (أو الأشكال) بحيث يمكن تمثيل كائنات متعددة لها الخصائص نفسها بالترتيب نفسه بكفاءة. تحتوي هذه الفئة على هذه الفئات المخفية، والتي تُعرف باسم system / Map (غير مرتبطة بـ JavaScript Map)، والبيانات ذات الصلة.

(sliced string)

عندما يحتاج V8 إلى أخذ سلسلة فرعية، مثلما يحدث عندما يستدعي رمز JavaScript String.prototype.substring()، قد يختار V8 تخصيص عنصر سلسلة مجزّأة بدلاً من نسخ جميع الأحرف ذات الصلة من السلسلة الأصلية. يحتوي هذا العنصر الجديد على مؤشر إلى السلسلة الأصلية ويصف نطاق الأحرف من السلسلة الأصلية المطلوب استخدامه.

من منظور رمز JavaScript، هذه مجرد سلاسل عادية، وتتصرف مثل أي سلسلة أخرى. إذا كانت سلسلة مجزّأة تحتفظ بمساحة كبيرة من الذاكرة، قد يكون البرنامج قد تسبّب في حدوث المشكلة 2869، وقد يستفيد من اتّخاذ خطوات مدروسة "لتسطيح" السلسلة المجزّأة.

system / Context

تحتوي الكائنات الداخلية من النوع system / Context على متغيّرات محلية من التضمين، وهو نطاق JavaScript يمكن لدالة متداخلة الوصول إليه.

يحتوي كل مثيل دالة على مؤشر داخلي إلى Context الذي يتم تنفيذه فيه، حتى يتمكن من الوصول إلى هذه المتغيّرات. على الرغم من أنّ عناصر Context لا تظهر مباشرةً من JavaScript، يمكنك التحكّم فيها مباشرةً.

(system)

تحتوي هذه الفئة على عناصر داخلية مختلفة لم يتم تصنيفها (حتى الآن) بطريقة أكثر وضوحًا.

عرض المقارنة

يتيح لك عرض المقارنة العثور على العناصر التي تم تسريبها من خلال مقارنة لقطات متعددة ببعضها. على سبيل المثال، عند تنفيذ إجراء ثم التراجع عنه، مثل فتح مستند وإغلاقه، يجب ألا يترك ذلك عناصر إضافية.

للتأكّد من عدم حدوث تسرُّب في عملية معيّنة:

  1. يُرجى أخذ لقطة لأجزاء من الذاكرة قبل تنفيذ عملية.
  2. نفِّذ عملية. وهذا يعني التفاعل مع صفحة بطريقة تعتقد أنّها قد تؤدي إلى تسرُّب البيانات.
  3. نفِّذ عملية عكسية. أي أنّه عليك تنفيذ التفاعل عكسيًا وتكراره بضع مرات.
  4. التقِط لقطة ثانية للذاكرة المؤقتة وغيِّر طريقة العرض إلى المقارنة، مع مقارنتها باللقطة 1.

تعرِض طريقة العرض المقارنة الفرق بين لقطاتَين. عند توسيع إدخال إجمالي، يتم عرض مثيلات العناصر المضافة والمحذوفة:

مقارنةً باللقطة 1.

عرض الاحتواء

يمكنك استخدام طريقة عرض الاحتواء للحصول على نظرة شاملة لبنية كائنات تطبيقك. يتيح لك هذا الإجراء الاطّلاع على الدوالّ المغلقة، وملاحظة العناصر الداخلية لوحدة افتراضية التي تشكّل معًا عناصر JavaScript، ومعرفة مقدار الذاكرة التي يستخدمها تطبيقك على مستوى منخفض جدًا.

يوفّر العرض عدة نقاط دخول:

  • عناصر DOMWindow كائنات عامة لرمز JavaScript.
  • جذور Google Cloud جذور جمع القمامة التي يستخدمها برنامج جمع القمامة في الجهاز الظاهري يمكن أن تتألف جذور جمع البيانات في الذاكرة من خرائط كائنات مدمجة وجداول رموز وبرامج VM لعمليات التجميع وذاكرة التخزين المؤقت للترجمة ونطاقات المعالِجات والمعالِجات الشاملة.
  • العناصر المدمجة: "دفع" عناصر المتصفح داخل جهاز JavaScript الافتراضي للسماح بالتشغيل الآلي، مثل عُقد DOM وقواعد CSS.

عرض &quot;الإجراءات الاحترازية&quot;

قسم Retainers

يعرض قسم العناصر التي تم الاحتفاظ بها في أسفل لوحة الذاكرة العناصر التي تشير إلى العنصر المحدّد في العرض. تعدِّل لوحة الذاكرة قسم العناصر المحفوظة عند اختيار عناصر مختلفة في أيّ من طرق العرض باستثناء الإحصاءات.

قسم &quot;أدوات الاحتفاظ باللقطات&quot;

في هذا المثال، تحتفظ السمة x مثيل Item بالسلسلة المحدّدة.

تجاهُل عمليات الاحتفاظ

يمكنك إخفاء العناصر الثابتة لمعرفة ما إذا كانت أي عناصر أخرى تحافظ على العنصر المحدّد. وباستخدام هذا الخيار، لن تحتاج أولاً إلى إزالة عملية الاحتفاظ هذه من الرمز ثم إعادة التقاط لقطة لأجزاء من الذاكرة.

خيار &quot;تجاهل هذا المبلغ المحجوز مؤقتًا&quot; في القائمة المنسدلة

لإخفاء عنصر احتياطي، انقر بزر الماوس الأيمن واختَر تجاهل هذا العنصر الاحتياطي. يتم وضع علامة ignored على المبالغ المحجوزة في الحساب الدائم والتي تم تجاهلها في عمود المسافة. لإيقاف تجاهل جميع العناصر المحفوظة، انقر على استعادة العناصر المحفوظة التي تم تجاهلها في شريط الإجراءات في أعلى الصفحة.

العثور على عنصر معيّن

للعثور على عنصر في الحزمة المجمّعة، يمكنك البحث باستخدام Ctrl + F وإدخال رقم تعريف العنصر.

تسمية الدوال لتمييز الدوال المغلقة

يساعد ذلك كثيرًا في تسمية الدوال حتى تتمكن من التمييز بين حالات الإغلاق في اللقطة.

على سبيل المثال، لا تستخدم التعليمة البرمجية التالية دوالًا مُسمّاة:

function createLargeClosure() {
  var largeStr = new Array(1000000).join('x');

  var lC = function() { // this is NOT a named function
    return largeStr;
  };

  return lC;
}

في حين أنّ هذا المثال يفعل ما يلي:

function createLargeClosure() {
  var largeStr = new Array(1000000).join('x');

  var lC = function lC() { // this IS a named function
    return largeStr;
  };

  return lC;
}

دالة مُسمّاة في عنصر إغلاق

الكشف عن عمليات تسرُّب نموذج DOM

يمكن لأداة تحليل الذاكرة عرض التبعيات الثنائية الاتجاه بين الكائنات الأصلية للمتصفّح (عقد DOM وقواعد CSS) وكائنات JavaScript. ويساعد ذلك في اكتشاف تسرُّبات غير مرئية تحدث بسبب أشجار DOM الفرعية المنسية التي تطفو من حولها.

يمكن أن تكون عمليات تسرُّب DOM أكبر مما تتصور. راجِع المثال التالي. متى يتم جمع مهملات #tree؟

  var select = document.querySelector;
  var treeRef = select("#tree");
  var leafRef = select("#leaf");
  var body = select("body");

  body.removeChild(treeRef);

  //#tree can't be GC yet due to treeRef
  treeRef = null;

  //#tree can't be GC yet due to indirect
  //reference from leafRef

  leafRef = null;
  //#NOW #tree can be garbage collected

يحتفظ العنصر #leaf بمرجع إلى العنصر الرئيسي (parentNode) وبشكل متكرر حتى العنصر #tree، لذا فإنّه عند إلغاء العنصر leafRef فقط تصبح الشجرة الكاملة ضمن العنصر #tree مرشحة للجمع.

الأشجار الفرعية لنموذج DOM