مصطلحات الذاكرة

Meggin Kearney
Meggin Kearney

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

تشير المصطلحات والمفاهيم الموضّحة هنا إلى أداة تحليل الذاكرة في "أدوات مطوّري البرامج في Chrome". إذا سبق لك استخدام Java أو ‎.NET أو أي أداة أخرى لتحليل الذاكرة، قد يكون هذا القسم مراجعة لك.

أحجام العناصر

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

تمثيل مرئي للذكرى

يمكن أن يحتفظ الكائن بالذاكرة بطريقتَين:

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

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

عمودَا "المساحة المسترجعة" و"المساحة السطحية" في لوحة "الذاكرة"

حجم مُصغَّر

هذا هو حجم الذاكرة التي يحتفظ بها الكائن نفسه.

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

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

الحجم المحفوظ

هذا هو حجم الذاكرة التي يتمّ تحريرها بعد حذف الكائن نفسه مع الكائنات التابعة له التي تمّ جعلها غير قابلة للوصول إليها من جذور جمع القمامة.

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

هناك الكثير من الجذور الداخلية في "الاستضافة في Google"، ومعظمها لا يهمّ المستخدمين. من وجهة نظر التطبيقات، هناك الأنواع التالية من الجذور:

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

يبدأ رسم بياني الذاكرة بجذر، والذي قد يكون window عنصر المتصفّح أو Global عنصر وحدة Node.js. لا يمكنك التحكّم في كيفية معالجة أداة "إدارة الذاكرة في Java" لهذا العنصر الجذر.

لا يمكن التحكّم في العنصر الجذر.

يتمّ جمع أيّ ملف لا يمكن الوصول إليه من الجذر.

الكائنات التي تحتفظ بالشجرة

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

  • يتم تصنيف العقد (أو الكائنات) باستخدام اسم دالة المنشئ التي تم استخدامها لإنشائها.
  • يتم تصنيف الحواف باستخدام أسماء السمات.

تعرَّف على كيفية تسجيل ملف شخصي باستخدام أداة تحليل الذاكرة. تشمل بعض العناصر الملفتة للنظر التي يمكننا رؤيتها في تسجيل Heap Profiler التالي المسافة: المسافة من جذر "جمع القمامة". إذا كانت جميع الأجسام من النوع نفسه تقريبًا على المسافة نفسها، وبعضها على مسافة أكبر، يُرجى التحقيق في ذلك.

مثال على المسافة من الجذر

المواقع الإلكترونية المهيمنة

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

في الرسم البياني التالي:

  • العقدة 1 تهيمن على العقدة 2
  • العقدة 2 تهيمن على العقد 3 و4 و6
  • العقدة 3 تهيمن على العقدة 5
  • العقدة 5 هي المسيطرة على العقدة 8
  • العقدة 6 هي المسيطرة على العقدة 7

بنية شجرة المُسودّين

في المثال التالي، العقدة #3 هي المُهيمن على #10، ولكنّ #7 متوفّرة أيضًا في كل مسار بسيط من GC إلى #10. وبالتالي، يكون الكائن "ب" هو المُهيمن على الكائن "أ" إذا كان "ب" موجودًا في كل مسار بسيط من الجذر إلى الكائن "أ".

صورة توضيحية متحركة لعنصر مهيمن

تفاصيل V8

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

تمثيل كائن JavaScript

هناك ثلاثة أنواع أساسية:

  • الأرقام (مثل 3.14159..)
  • القيم المنطقية (صحيح أو خطأ)
  • السلاسل (مثل 'Werner Heisenberg')

ولا يمكنها الإشارة إلى قيم أخرى، وتكون دائمًا أوراقًا أو عقدًا نهائية.

يمكن تخزين الأرقام على النحو التالي:

  • قيم عدد صحيح فورية 31 بت تُعرف باسم الأرقام الصحيحة الصغيرة (SMIs)، أو
  • عناصر الحِزم، والتي يُشار إليها باسم أرقام الحِزم تُستخدَم أرقام الحِزم لتخزين القيم التي لا تلائم نموذج SMI، مثل الأرقام المزدوجة، أو عندما تحتاج القيمة إلى التضمين، مثل ضبط السمات عليها.

يمكن تخزين السلاسل في أيٍّ مما يلي:

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

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

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

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

على سبيل المثال، إذا جمعت أ وب، ستحصل على سلسلة (أ، ب) التي تمثّل نتيجة التسلسل. إذا تم تسلسل d لاحقًا مع هذه النتيجة، ستحصل على سلسلة cons أخرى ((a, b)، d).

المصفوفات: المصفوفة هي عنصر يتضمّن مفاتيح رقمية. ويتم استخدامها على نطاق واسع في آلة V8 الافتراضية لتخزين كميات كبيرة من البيانات. يتم الاحتفاظ بمجموعات أزواج المفاتيح والقِيم المستخدَمة مثل القواميس في ملف سحابي باستخدام المصفوفات.

يمكن أن يكون كائن JavaScript نموذجيًا أحد نوعَي الصفيفَين المستخدَمَين للتخزين:

  • المواقع المُسمّاة
  • العناصر الرقمية

في الحالات التي يتوفّر فيها عدد صغير جدًا من السمات، يمكن تخزينها داخليًا في كائن JavaScript نفسه.

الخريطة: عنصر يصف نوع العنصر وتنسيقه على سبيل المثال، تُستخدَم الخرائط لتحديد التسلسلات الهرميّة للعناصر الضمنية من أجل الوصول السريع إلى السمات.

مجموعات الكائنات

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

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