مراقبة كل الذاكرة التي تستخدمها صفحة الويب: performance.measureMemory ()

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



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

const object = { a: new Array(1000), b: new Array(2000) };
setInterval(() => console.log(object.a), 1000);

هناك مصفوفة كبيرة غير ضرورية هنا b، لكن المتصفح لا يحرر الذاكرة التي يشغلها نظرًا لأنه يمكن الوصول إليها من خلال خاصية الكائن object.bفي رد الاتصال. ونتيجة لذلك ، تتسرب الذاكرة التي تشغلها هذه المجموعة.

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

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

ما أوجه الاختلاف بين واجهة برمجة تطبيقات Performance.measureMemory () الجديدة عن Performance.memory القديمة؟


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

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

الطرق الموصى بها لاستخدام واجهة برمجة التطبيقات الجديدة


يعتمد استخدام الذاكرة بواسطة صفحات الويب على وقوع الأحداث ، وعلى إجراءات المستخدم ، وعلى جمع القمامة. لهذا السبب تم performance.measureMemory()تصميم واجهة برمجة التطبيقات لدراسة مستوى استخدام الذاكرة في الإنتاج. نتائج استدعاء API هذا في بيئة اختبار أقل فائدة. فيما يلي أمثلة لخيارات استخدامه:

  • - .
  • A/B- , .
  • .
  • , . .


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

تقدم العمل الحالي


خطوةحالة
1. إنشاء تفسيرات API
منجز
2. إنشاء مشروع مواصفة
نفذت
3. جمع التعليقات وإنهاء المشروع
نفذت
4. اختبارات الإصدار التجريبي
نفذت
5. إطلاق
لم يبدأ

باستخدام performance.measureMemory ()


▍ تمكين دعم Origin التجريبي


واجهة برمجة التطبيقات performance.measureMemory()متاحة في Chrome 83 وفقًا لنظام Origin Trial. من المتوقع أن تنتهي هذه المرحلة بإصدار Chrome 84.

يسمح Origin Trial للمطورين بالاستفادة من ميزات Chrome الجديدة ومشاركة التعليقات حول راحة هذه الميزات وسهولة استخدامها وفعاليتها مع مجتمع الويب. يمكن العثور على تفاصيل حول هذا البرنامج هنا . يمكنك الاشتراك في البرنامج على صفحة التسجيل.

istrationالتسجيل في برنامج Origin Trial


  1. طلب رمز مميز للفرصة التي تهمك.
  2. أضف الرمز المميز إلى صفحات المشروع التجريبي. هناك طريقتان للقيام بذلك:

    • أضف <meta>علامة origin-trialإلى عنوان كل صفحة. على سبيل المثال، قد تبدو مثل هذا: <meta http-equiv="origin-trial" content="TOKEN_GOES_HERE">.
    • إذا كان لديك حق الوصول إلى إعدادات الخادم ، فيمكنه إضافة رمز مميز باستخدام رأس HTTP Origin-Trial. ونتيجة لذلك، يجب أن يظهر رأس استجابة شيء من هذا القبيل ما يلي: Origin-Trial: TOKEN_GOES_HERE.

n تمكين ميزة جديدة من خلال أعلام Chrome


من أجل تجربة performance.measureMemory()، في حين الاستغناء عن رمز المنشأ الابتدائية، تحتاج إلى تمكين العلامة #experimental-web-platform-featuresفي chrome://flags.

▍تحقق من استخدام API


performance.measureMemory()قد يفشل استدعاء دالة ، مع طرح SecurityError . يمكن أن يحدث هذا إذا كانت البيئة لا تلبي متطلبات الأمان لتسريبات المعلومات. أثناء اختبار Origin Trial في Chrome ، تتطلب واجهة برمجة التطبيقات هذه تضمين عزل الموقع . عندما تكون واجهة برمجة التطبيقات جاهزة للاستخدام العادي ، ستعتمد على الخاصية crossOriginIsolated . يمكن تشغيل صفحة ويب في هذا الوضع عن طريق تعيين رؤوس COOP و COEP .

هنا عينة من الكود:

if (performance.measureMemory) {
  let result;
  try {
    result = await performance.measureMemory();
  } catch (error) {
    if (error instanceof DOMException &&
        error.name === "SecurityError") {
      console.log("The context is not secure.");
    } else {
      throw error;
    }
  }
  console.log(result);
}

testing الاختبار المحلي


يأخذ Chrome قياس الذاكرة عند جمع القمامة. وهذا يعني أن الوصول إلى API لا يحل الوعد على الفور. للحصول على النتيجة ، تحتاج إلى انتظار جلسة جمع القمامة التالية. يبدأ API بالقوة جمع البيانات المهملة بعد مهلة معينة ، والتي يتم تعيينها حاليًا على 20 ثانية. إذا قمت بتشغيل Chrome بعلامة سطر الأوامر --enable-blink-features='ForceEagerMeasureMemory'، فسيتم تقليل المهلة إلى الصفر ، وهو أمر مفيد لتصحيح الأخطاء المحلية والاختبار المحلي.

مثال


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

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

function scheduleMeasurement() {
  if (!performance.measureMemory) {
    console.log("performance.measureMemory() is not available.");
    return;
  }
  const interval = measurementInterval();
  console.log("Scheduling memory measurement in " +
      Math.round(interval / 1000) + " seconds.");
  setTimeout(performMeasurement, interval);
}

//       .
window.onload = function () {
  scheduleMeasurement();
}

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

function measurementInterval() {
  const MEAN_INTERVAL_IN_MS = 5 * 60 * 1000;
  return -Math.log(Math.random()) * MEAN_INTERVAL_IN_MS;
}

ونتيجة لذلك ، performMeasurement()تستدعي الوظيفة غير المتزامنة واجهة برمجة التطبيقات لدينا ، وتسجل النتيجة ، وتخطط للقياس التالي.

async function performMeasurement() {
  // 1.  performance.measureMemory().
  let result;
  try {
    result = await performance.measureMemory();
  } catch (error) {
    if (error instanceof DOMException &&
        error.name === "SecurityError") {
      console.log("The context is not secure.");
      return;
    }
    //    .
    throw error;
  }
  // 2.  .
  console.log("Memory usage:", result);
  // 3.   .
  scheduleMeasurement();
}

قد تبدو نتائج القياس كما يلي:

// ,    :
{
  bytes: 60_000_000,
  breakdown: [
    {
      bytes: 40_000_000,
      attribution: ["https://foo.com"],
      userAgentSpecificTypes: ["Window", "JS"]
    },
    {
      bytes: 20_000_000,
      attribution: ["https://foo.com/iframe"],
      userAgentSpecificTypes: ["Window", "JS"]
    }
  ]
}

يتم عرض تقدير المستوى العام لاستخدام الذاكرة في هذا المجال bytes. عند اشتقاق هذا التقدير ، يتم استخدام فواصل أرقام الأرقام. هذه القيم تعتمد إلى حد كبير على التنفيذ. إذا تم تلقيها لمتصفحات مختلفة ، فلا يمكنك مقارنتها. يمكن أن تختلف طريقة الحصول عليها حتى في الإصدارات المختلفة من نفس المتصفح. بينما يستمر برنامج Origin Trial ، تتضمن قيم الإرجاع مؤشرات لاستخدام ذاكرة JavaScript حسب النافذة الرئيسية ، ومؤشرات استخدام الذاكرة لعناصر iframeمن نفس الموقع ، ومؤشرات للنوافذ ذات الصلة. عندما تكون واجهة برمجة التطبيقات جاهزة ، ستكون هذه القيمة معلومات حول الذاكرة التي تستهلكها جافا سكريبت و DOM وجميع العناصر iframeالمرتبطة بالنوافذ وعامل الويب.

قائمةbreakdownيعطي معلومات أكثر تفصيلاً عن الذاكرة المستخدمة. يصف كل إدخال جزءًا من الذاكرة ويربط هذا الجزء بمجموعة من النوافذ iframeأو العناصر أو العمال المحددة بواسطة عنوان URL. userAgentSpecificTypesيسرد الحقل أنواع الذاكرة التي تحددها ميزات التنفيذ.

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

ردود الفعل


سيكون من دواعي سرور مجموعة مجتمع أداء الويب وفريق تطوير Chrome معرفة ما تفكر فيه performance.measureMemory()والتعرف على تجربتك باستخدام واجهة برمجة التطبيقات هذه.

شاركنا أفكارك حول جهاز API


هل هناك شيء في واجهة برمجة التطبيقات لا يعمل كما هو متوقع؟ ربما تفتقر إلى شيء تحتاجه لتنفيذ فكرتك؟ افتح مهمة جديدة في متعقب المشروع أو علّق على مهمة موجودة.

الإبلاغ عن مشكلة في التنفيذ


هل وجدت خطأ في تنفيذ Chrome؟ أو ربما اتضح أن التنفيذ يختلف عن المواصفات؟ سجّل الخطأ هنا: new.crbug.com . حاول تضمين أكبر قدر ممكن من التفاصيل في رسالتك ، وقم بتضمين تعليمات بسيطة حول كيفية إعادة إظهار الخطأ ، ووضح أن المشكلة تتعلق Blink>PerformanceAPIs. الخلل هو طريقة جيدة للغاية لإثبات الأخطاء .

ادعمنا


performance.measureMemory()هل تخطط للاستخدام ؟ إذا كان الأمر كذلك ، أخبرنا عنه. تساعد هذه القصص فريق تطوير Chrome على تحديد الأولويات. تظهر هذه القصص لمنشئي المتصفحات الأخرى أهمية دعم الميزات الجديدة. إذا أردت ، أرسل تغريدة إلى ChromiumDev وأخبرنا عن مكان وكيفية استخدام API الجديد.

القراء الأعزاء! هل حاولت performance.measureMemory()؟


All Articles