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

Meggin Kearney
Meggin Kearney
Sofia Emelianova
Sofia Emelianova

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

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

أخذ لقطة

لالتقاط لقطة لأجزاء من الذاكرة:

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

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

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

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

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

لقطة لعناصر متعدّدة من العناصر المبعثرة.

محو اللقطات

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

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

عرض اللقطات

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

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

طريقة عرض الملخص المحددة من القائمة المنسدلة في أعلى الصفحة.

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

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

طريقة العرض "الملخص" بدالة إنشائية موسّعة.

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

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

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

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

فلاتر طريقة الإنشاء

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

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

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

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

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

  • الدوال المضمنة مثل Array أو Object.
  • الدوال التي حددتها في التعليمة البرمجية.
  • الفئات الخاصة التي لا تستند إلى الدوال الإنشائية.

إدخالات أداة الإنشاء

(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 for Testing واتّبِع ما يلي:

  1. افتح "أدوات مطوري البرامج" وفعِّل الإعدادات الإعدادات > التجارب > check_box إظهار الخيار لعرض العناصر الداخلية في لقطات لأجزاء من الذاكرة.
  2. افتح لوحة الذاكرة، واختَر radio_button_checked لقطة لأجزاء من الذاكرة، ثم فعِّل radio_button_checked عرض الإعدادات الداخلية (يتضمّن تفاصيل إضافية خاصة بعملية التنفيذ).
  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.
  • جذور GC: جذور البيانات المهملة التي تستخدمها أداة تجميع البيانات المهملة في الجهاز الافتراضي (VM). يمكن أن تتألف جذور تجميع البيانات المهملة من خرائط كائنات مضمّنة وجداول الرموز وحِزم سلاسل الأجهزة الافتراضية وذاكرات التخزين المؤقت للتجميع ونطاقات المقبض وأسماء المؤشرات العامة.
  • العناصر المدمجة مع المحتوى: "دفع" عناصر المتصفح داخل جهاز JavaScript الافتراضي للسماح بالتشغيل الآلي، مثل عُقد DOM وقواعد CSS.

طريقة عرض الاحتواء.

قسم Retainers

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

قسم Retainers.

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

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

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

خيار "تجاهل عملية الاحتفاظ هذه" في القائمة المنسدلة.

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

البحث عن عنصر معيّن

للعثور على عنصر في الذاكرة المجمّعة، يمكنك البحث باستخدام 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