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

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 جذور جمع القمامة التي يستخدمها برنامج جمع القمامة في الجهاز الظاهري يمكن أن تتألف جذور جمع القمامة من خرائط كائنات مدمجة وجداول رموز وبرامج ذاكرة تخزين مؤقت للترجمة وبرامج ذاكرة تخزين مؤقت للترجمة ونطاقات معالِمات ومعالِمات عامة.
  • العناصر المدمجة: كائنات المتصفّح التي يتمّ "دفعها" داخل الآلة الافتراضية لبرنامج JavaScript للسماح بالتشغيل الآلي، مثل عقد DOM وقواعد CSS

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

قسم "أدوات الاحتفاظ باللقطات"

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

قسم &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