إدارة فعالة للذاكرة على نطاق Gmail

Loreena Lee
Loreena Lee

مقدمة

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

جلسة Google I/O 2013

قدمنا هذه المواد في مؤتمر Google I/O لعام 2013. يمكنك مشاهدة الفيديو أدناه:

Gmail، لدينا مشكلة...

كان فريق Gmail يواجه مشكلة خطيرة. يتزايد عدد الأشخاص الذين يسمعون عن علامات تبويب Gmail التي تستهلك العديد من وحدات الغيغابايت من الذاكرة على أجهزة الكمبيوتر المحمولة وأجهزة سطح المكتب المحدودة الموارد، وغالبًا ما يكون ذلك مع الانتهاء من إغلاق المتصفح بأكمله. قصص عن تثبيت وحدات المعالجة المركزية (CPU) بنسبة %100 واستخدام تطبيقات لا تستجيب وعلامات تبويب Chrome الحزينة ("مات يا جميل"). كان الفريق في حيرة من أمره بشأن كيفية البدء في تشخيص المشكلة، ناهيك عن إصلاحها. ولم تكن لديهم أي فكرة عن مدى انتشار المشكلة ولم تتوسع الأدوات المتاحة لتشمل التطبيقات الكبيرة. وتعاون الفريق مع فِرق Chrome، وطوّروا معًا أساليب جديدة لتصنيف مشاكل الذاكرة، وحسّنوا الأدوات الحالية، وأتاحوا جمع بيانات الذاكرة من الميدان. قبل الانتقال إلى الأدوات، لنتناول أساسيات إدارة ذاكرة JavaScript.

أساسيات إدارة الذاكرة

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

الأنواع الأساسية

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

  1. رقم (مثل 4، 3.14159)
  2. منطقي (صحيح أو خطأ)
  3. سلسلة ("Hello World")

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

هناك نوع حاوية واحد فقط، وهو الكائن. في JavaScript، يكون الكائن صفيفًا ارتباطيًا. العنصر غير الفارغ هو عقدة داخلية بها حواف صادرة لقيم أخرى (عُقد).

ماذا عن الصفائف؟

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

المصطلحات

  1. القيمة: مثيل من النوع الأساسي أو كائن أو مصفوفة أو غير ذلك
  2. المتغير: اسم يشير إلى قيمة.
  3. الخاصية - اسم في كائن يشير إلى قيمة.

الرسم البياني للكائنات

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

الرسم البياني للكائنات

متى تتحول القيمة إلى نفايات؟

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

الرسم البياني غير الصحيح

ما هو تسرُّب الذاكرة في JavaScript؟

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

email.message = document.createElement("div");
displayList.appendChild(email.message);

وبعد ذلك، يمكنك إزالة العنصر من قائمة العرض:

displayList.removeAllChildren();

لن تتم إزالة عنصر DOM المشار إليه في الرسالة ما دامت السمة email متوفّرة، على الرغم من أنّه أصبح الآن منفصلاً عن شجرة نموذج العناصر في المستند (DOM) للصفحة.

ما هو Bloat؟

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

ما هي "مجموعة القمامة"؟

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

V8 وحدة تجميع القمامة بالتفصيل

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

جامعي الأجيال

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

من الناحية العملية، لا تدوم القيم المخصّصة حديثًا لفترة طويلة. أظهرت دراسة أجرتها برامج Smalltalk أن 7% فقط من القيم تبقى على قيد الحياة بعد مجموعة من جيل الشباب. وقد توصّلت دراسات مماثلة عبر أوقات التشغيل إلى أنّ ما بين 90% و 70% من القيم المخصّصة حديثًا لا يتم اعتمادها أبدًا في الجيل القديم.

جيل الشباب

تنقسم كومة الذاكرة المؤقتة من جيل الشباب في V8 إلى مساحتين، تتم تسميتها من وإلى. يتم تخصيص الذاكرة من المساحة إلى الأخرى. عملية التخصيص سريعة جدًا، إلى أن تمتلئ مساحة "إلى"، وعندها يتم إنشاء مجموعة من الجيل الجديد. تعمل مجموعة "الأجيال الجديدة" أولاً على تبديل الحياة من وإلى الفضاء، بينما يتم مسح القديم إلى الفضاء (الآن من الفضاء) ويتم نسخ جميع القيم الحية إلى الفضاء أو نقلها إلى الجيل القديم. وتستغرق أي مجموعة نموذجية من الجيل الأصغر مدة 10 مللي ثانية (مللي ثانية).

ومن البديهي، أن تفهموا أنّ كل عملية تخصيص يجنيها تطبيقكم تشتت انتباهكم من المساحة وتؤدي إلى إيقاف تجميع البيانات المهملة مؤقتًا. يُرجى على مطوّري الألعاب ملاحظة ما يلي: لضمان أنّ وقت عرض اللقطة 16 ملي ثانية (المطلوب تحقيق 60 لقطة في الثانية)، يجب ألا يُخصّص تطبيقك أي تخصيصات، لأنّ مجموعة واحدة من جيل الشباب ستستهلك معظم وقت عرض اللقطة.

لقطات مؤثّرة من جيل الشباب

الإصدار القديم

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

ملخّص GC V8

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

إصلاح Gmail

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

الأدوات والأساليب

بيانات الحقل وواجهة برمجة التطبيقات Performance.memory

اعتبارًا من إصدار Chrome 22، سيتم تفعيل performance.memory API تلقائيًا. بالنسبة إلى التطبيقات طويلة الأمد مثل Gmail، تكون البيانات الواردة من المستخدمين الحقيقيين في غاية الأهمية. وتتيح لنا هذه المعلومات التمييز بين المستخدمين المتمرسين - الذين يقضون من 8 إلى 16 ساعة في اليوم على Gmail، ويتلقىون مئات الرسائل يوميًا - من المستخدمين العاديين الذين يقضون بضع دقائق يوميًا في Gmail، ويتلقىون عشرات الرسائل تقريبًا في الأسبوع.

تعرض واجهة برمجة التطبيقات هذه ثلاث أجزاء من البيانات:

  1. jsheapSizeLIMIT - مقدار الذاكرة (بالبايت) الذي تقتصر عليه كومة JavaScript.
  2. totalJSHeapSize: مقدار الذاكرة (بالبايت) التي خصصتها كومة JavaScript بما في ذلك المساحة الخالية.
  3. useJSHeapSize - حجم الذاكرة (بالبايت) المستخدم حاليًا.

يُرجى العلم أنّ واجهة برمجة التطبيقات تعرض قيم الذاكرة لجميع عمليات استخدام Chrome بالكامل. على الرغم من أنّه ليس الوضع التلقائي، قد يفتح Chrome علامات تبويب متعدّدة في عملية العارض نفسها في ظروف معيّنة. وهذا يعني أنّ القيم التي تعرِضها Performance.memory قد تحتوي على المساحة المستخدَمة من الذاكرة لعلامات تبويب المتصفّح الأخرى بالإضافة إلى تلك التي تحتوي على تطبيقك.

قياس الذاكرة على نطاق واسع

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

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

قياس الذاكرة على نطاق واسع

تحديد مشكلة الذاكرة باستخدام المخطط الزمني لأدوات مطوّري البرامج

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

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

إثبات وجود مشكلة

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

رسم بياني على شكل سنّ منشار

بعد التأكّد من ظهور المشكلة، يمكنك الحصول على المساعدة في تحديد مصدر المشكلة من خلال أداة تحليل العناصر في أدوات مطوّري البرامج.

رصد حالات تسرّب الذاكرة باستخدام محلّل تعداد العناصر في أدوات مطوّري البرامج

توفر لوحة المحلل كلًا من محلّل وحدة المعالجة المركزية (CPU) ومحلِّل Heap. يعمل تحليل عناصر الذاكرة من خلال أخذ لقطة من الرسم البياني للكائنات. قبل أخذ لقطة، يجمّع كل من الأجيال الصغيرة والكبار البيانات غير الصحيحة. بمعنى آخر، ستظهر لك فقط القيم التي كانت نشطة عند التقاط اللقطة.

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

استخدام محلّل تخصيص أجزاء كبيرة

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

محلّل تخصيص لقطات لعناصر متعدّدة

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

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

حل مشكلة الذاكرة في Gmail

باستخدام الأدوات والتقنيات التي تمت مناقشتها أعلاه، تمكّن فريق Gmail من تحديد بعض فئات الأخطاء: ذاكرات التخزين المؤقت غير المحدودة، وعددًا لا حصر له من صفائف معاودة الاتصال التي تنتظر حدوث شيء لا يحدث في الواقع، واحتفاظ مستمعي الأحداث بأهدافهم بدون قصد. من خلال إصلاح هذه المشاكل، انخفض الاستخدام الإجمالي للذاكرة في Gmail بشكل كبير. واستهلك المستخدمون ضمن النسبة 99% ذاكرة أقل بنسبة 80% عن ذي قبل، وانخفض استهلاك الذاكرة للمستخدمين المتوسطين بنسبة 50% تقريبًا.

استخدام الذاكرة في Gmail

وبما أنّ Gmail استهلك ذاكرة أقل، تم تقليل وقت استجابة "إيقاف Google المؤقت" مؤقتًا، ما أدّى إلى زيادة تجربة المستخدم بشكل عام.

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

الحث على اتخاذ إجراء

اسأل نفسك هذه الأسئلة التالية:

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

الخلاصة

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