إذا لم تتمكّن من قياسه، لن تتمكّن من تحسينه.
Lord Kelvin
لتشغيل ألعاب HTML5 بشكل أسرع، عليك أولاً تحديد نقاط الاختناق في الأداء، ولكن قد يكون ذلك صعبًا. يُعدّ تقييم بيانات عدد اللقطات في الثانية (FPS) بداية جيدة، ولكن لمعرفة الصورة الكاملة، عليك فهم الفروق الدقيقة في أنشطة Chrome.
توفّر أداة about:tracing
الإحصاءات التي تساعدك في تجنُّب الحلول المؤقتة المتسرّعة التي تهدف إلى تحسين الأداء، ولكنها في الأساس تخمينات حسنة النية. سيساعدك ذلك في توفير الكثير من الوقت والجهد، والحصول على صورة أوضح لما يفعله Chrome مع كل لقطة، واستخدام هذه المعلومات لتحسين لعبتك.
مرحبًا about:tracing
تمنحك أداة about:tracing
في Chrome نظرة على جميع أنشطة Chrome على مدار فترة زمنية معيّنة بدقة عالية قد تبدو لك مربكة في البداية. تمّت تجهيز العديد من الدوالّ في Chrome لتتبُّع الأداء تلقائيًا، لذا يمكنك استخدام about:tracing
لتتبُّع أدائك بدون إجراء أيّ عملية تجهيز يدوية. (اطّلِع على قسم لاحق عن قياس أداء JavaScript يدويًا).
للاطّلاع على عرض التتبّع، ما عليك سوى كتابة about:tracing في مربّع Chrome المتعدّد الاستخدامات (شريط العناوين).
.من أداة التتبّع، يمكنك بدء التسجيل وتشغيل لعبتك لبضع ثوانٍ، ثم عرض بيانات التتبّع. في ما يلي مثال على الشكل الذي قد تظهر به البيانات:
نعم، هذا أمر مربك. لنتحدّث عن كيفية قراءته.
يمثّل كل صف عملية يتم تحليلها، ويشير المحور من اليمين إلى اليسار إلى الوقت، وكل مربّع ملون هو عبارة عن طلب دالة تم قياس أدائه. تتوفّر صفوف لعدد من الأنواع المختلفة من الموارد. إنّ أكثر الوظائف التي تهمّك في تحليل أداء الألعاب هي CrGpuMain التي تعرض ما تفعله وحدة معالجة الرسومات (GPU) وCrRendererMain. يحتوي كلّ تتبُّع على أسطر CrRendererMain لكلّ علامة تبويب مفتوحة خلال فترة التتبُّع (بما في ذلك علامة التبويب about:tracing
نفسها).
عند قراءة بيانات التتبّع، تكون مهمتك الأولى هي تحديد صف CrRendererMain الذي يتوافق مع لعبتك.
في هذا المثال، المرشحان هما: 2216 و6516. لا تتوفّر حاليًا طريقة محسّنة لاختيار تطبيقك إلا البحث عن السطر الذي يُجري الكثير من التعديلات الدورية (أو إذا كنت قد زوّدت الرمز يدويًا بنقاط تتبُّع، ابحث عن السطر الذي يحتوي على بيانات التتبُّع). في هذا المثال، يبدو أنّ 6516 يشغّل حلقة رئيسية من تكرار التعديلات. إذا أغلقت جميع علامات التبويب الأخرى قبل بدء التتبُّع، سيكون من الأسهل العثور على CrRendererMain الصحيح. ولكن قد تظل هناك صفوف CrRendererMain لعمليات أخرى غير لعبتك.
العثور على الإطار
بعد تحديد الصف الصحيح في أداة التتبّع للعبة، تكون الخطوة التالية هي العثور على الحلقة الرئيسية. تبدو حلقة التكرار الرئيسية مثل نمط متكرر في بيانات التتبّع. يمكنك التنقّل في بيانات التتبُّع باستخدام مفاتيح W وA وS وD: A وD للانتقال لليسار أو لليمين (للخلف والأمام في الوقت) وW وS للتكبير والتصغير في البيانات. من المفترض أن تكون حلقة الألعاب الرئيسية عبارة عن نمط يتكرر كل 16 ملي ثانية إذا كانت اللعبة تعمل بمعدّل 60 هرتز.
بعد تحديد مدة عرض اللقطة في لعبتك، يمكنك الاطّلاع على ما تفعله التعليمات البرمجية بالضبط في كل لقطة. استخدِم W وA وS وD للتكبير إلى أن تتمكّن من قراءة النص في مربّعات الدوال.
تعرض هذه المجموعة من المربّعات سلسلة من طلبات الدالة، ويتم تمثيل كل طلب بمربّع ملون. تم استدعاء كل وظيفة من خلال المربّع أعلاها، لذا في هذه الحالة، يمكنك الاطّلاع على أنّ MessageLoop::RunTask استدعى RenderWidget::OnSwapBuffersComplete، الذي استدعى بدوره RenderWidget::DoDeferredUpdate، وما إلى ذلك. من خلال قراءة هذه البيانات، يمكنك الحصول على عرض كامل لما تم استدعاؤه ومدة كل تنفيذ.
ولكن إليك بعض التفاصيل. المعلومات التي يعرضها about:tracing
هي طلبات الدالة الأوّلية من رمز Chrome المصدر. يمكنك إجراء تخمينات مدروسة حول ما تفعله كل دالة من خلال الاسم، ولكن المعلومات ليست سهلة الاستخدام تمامًا. من المفيد الاطّلاع على المسار العام للإطار، ولكنك تحتاج إلى تنسيق يسهل فهمه لمعرفة ما يحدث.
إضافة علامات التتبّع
لحسن الحظ، تتوفّر طريقة سهلة لإضافة أدوات قياس يدوية إلى الرمز البرمجي لإنشاء بيانات التتبّع: console.time
وconsole.timeEnd
.
console.time("update");
update();
console.timeEnd("update");
console.time("render");
update();
console.timeEnd("render");
ينشئ الرمز أعلاه مربّعات جديدة في اسم عرض التتبّع باستخدام العلامات المحدّدة، لذلك إذا أعدت تشغيل التطبيق، ستظهر لك مربّعات "العرض" و"العرض المرئي" اللتان تعرضان الوقت المستغرَق بين طلبات البدء والانتهاء لكل علامة.
باستخدام هذا الإجراء، يمكنك إنشاء بيانات تتبُّع يفهمها الإنسان لتتبُّع النقاط الساخنة في الرمز البرمجي.
وحدة معالجة الرسومات أم وحدة المعالجة المركزية؟
في الرسومات المستندة إلى تسريع الأجهزة، من أهم الأسئلة التي يمكنك طرحها أثناء تحليل الأداء ما يلي: هل هذا الرمز مرتبط بوحدة معالجة الرسومات أم بوحدة المعالجة المركزية؟ مع كل لقطة، ستُجري بعض عمليات المعالجة على وحدة معالجة الرسومات وبعض العمليات المنطقية على وحدة المعالجة المركزية. لفهم ما يجعل لعبتك بطيئة، عليك معرفة كيفية توزيع العمل على الموردَين.
أولاً، ابحث عن السطر في عرض التتبُّع المُسمى CrGPUMain، والذي يشير إلى ما إذا كانت وحدة معالجة الرسومات مشغولة في وقت معيّن.
يمكنك ملاحظة أنّ كل لقطة من لعبتك تؤدي إلى تشغيل وحدة المعالجة المركزية في CrRendererMain بالإضافة إلى وحدة معالجة الرسومات. يعرض التتبّع أعلاه حالة استخدام بسيطة جدًا تكون فيها كلّ من وحدة المعالجة المركزية ووحدة معالجة الرسومات في وضع السكون لمعظم كلّ لقطة مدتها 16 ملي ثانية.
يصبح عرض التتبّع مفيدًا حقًا عندما تكون لديك لعبة تعمل ببطء ولا تكون متأكّدًا من المورد الذي تستنفده إلى أقصى حد. إنّ النظر في كيفية ارتباط سطور وحدة معالجة الرسومات ووحدة المعالجة المركزية هو مفتاح تصحيح الأخطاء. خذ المثال نفسه كما في السابق، ولكن أضِف بعض العمل الإضافي في حلقة التعديل.
console.time("update");
doExtraWork();
update(Math.min(50, now - time));
console.timeEnd("update");
console.time("render");
render();
console.timeEnd("render");
سيظهر لك الآن تتبع بالشكل التالي:
ماذا يخبرنا هذا التتبّع؟ نرى أنّ اللقطة المعروضة تتراوح بين 2270 ملي ثانية و2320 ملي ثانية تقريبًا، ما يعني أنّ كل لقطة تستغرق 50 ملي ثانية تقريبًا (معدّل لقطات يبلغ 20 هرتز). يمكنك رؤية أجزاء من مربّعات ملونة تمثّل وظيفة المعالجة بجانب مربّع التعديل، ولكنّ الإطار يهيمن عليه التعديل نفسه بالكامل.
على عكس ما يحدث في وحدة المعالجة المركزية، يمكنك ملاحظة أنّ وحدة معالجة الرسومات لا تزال غير نشطة في معظم أجزاء كل إطار. لتحسين هذا الرمز، يمكنك البحث عن العمليات التي يمكن إجراؤها في رمز برنامج تشويش الصورة ونقلها إلى وحدة معالجة الرسومات للاستفادة إلى أقصى حد من الموارد.
ماذا لو كان رمز برنامج تشويش الألوان بطيئًا ووحدة معالجة الرسومات مشغولة جدًا؟ ماذا لو أزلنا العمل غير الضروري من وحدة المعالجة المركزية وأضفنا بدلاً من ذلك بعض الأعمال في رمز برنامج Shader للشرائح؟ في ما يلي برنامج تشويش مكلف بشكل غير ضروري:
#ifdef GL_ES
precision highp float;
#endif
void main(void) {
for(int i=0; i<9999; i++) {
gl_FragColor = vec4(1.0, 0, 0, 1.0);
}
}
كيف يبدو تتبع الرمز الذي يستخدم هذا المخطِّط اللوني؟
يُرجى ملاحظة مدة الإطار مرة أخرى. في هذا المثال، يتراوح النمط المتكرر بين 2750 ملي ثانية و2950 ملي ثانية، أي مدة 200 ملي ثانية (معدل عرض اللقطات 5 هرتز تقريبًا). يكون سطر CrRendererMain فارغًا بالكامل تقريبًا، ما يعني أنّ وحدة المعالجة المركزية تكون في وضع السكون معظم الوقت، بينما تكون وحدة معالجة الرسومات مشغولة بشكل زائد. هذه علامة أكيدة على أنّ تأثيرات التظليل ثقيلة جدًا.
إذا لم تكن على دراية بالسبب الدقيق لانخفاض معدّل عرض اللقطات، يمكنك رصد معدل التحديث البالغ 5 هرتز والميل إلى الانتقال إلى رمز اللعبة والبدء في محاولة تحسين منطق اللعبة أو إزالته. في هذه الحالة، لن يكون ذلك مفيدًا على الإطلاق، لأنّ المنطق في حلقة اللعبة ليس هو ما يستغرق الوقت. في الواقع، يشير هذا التتبّع إلى أنّ تنفيذ المزيد من المهام على وحدة المعالجة المركزية في كلّ لقطة سيكون "مجانيًا" بشكل أساسي لأنّ وحدة المعالجة المركزية تكون في وضع الخمول، لذا فإنّ تكليفها بمهام إضافية لن يؤثّر في الوقت الذي تستغرقه اللقطة.
أمثلة حقيقية
لنلقِ نظرة الآن على شكل بيانات التتبّع من لعبة حقيقية. من الميزات الرائعة للألعاب المُنشأة باستخدام تكنولوجيات الويب المفتوحة أنّها تتيح لك الاطّلاع على آخر الأخبار حول منتجاتك المفضّلة. إذا كنت تريد اختبار أدوات التحليل، يمكنك اختيار عنوان WebGL المفضّل لديك من "سوق Chrome الإلكتروني" وتحليله باستخدام about:tracing
. في ما يلي مثال على عملية تتبُّع مأخوذة من لعبة Skid Racer الرائعة التي تعمل على WebGL.
يبدو أنّ كل لقطة تستغرق 20 ملي ثانية تقريبًا، ما يعني أنّ عدد اللقطات في الثانية يبلغ 50 لقطة تقريبًا. يمكنك ملاحظة أنّ العمل متوازن بين وحدة المعالجة المركزية ووحدة معالجة الرسومات، ولكن وحدة معالجة الرسومات هي المورد الأكثر طلبًا. إذا أردت الاطّلاع على أمثلة حقيقية لتحليل أداء ألعاب WebGL، جرِّب بعض عناوين "سوق Chrome الإلكتروني" التي تم إنشاؤها باستخدام WebGL، بما في ذلك:
الخاتمة
إذا كنت تريد تشغيل لعبتك بمعدّل 60 هرتز، يجب أن تتوافق جميع عملياتك مع مدة 16 ملي ثانية لوحدة المعالجة المركزية و16 ملي ثانية لوحدة معالجة الرسومات لكل لقطة. لديك موردان يمكن استخدامهما بشكل موازٍ، ويمكنك نقل العمل بينهما لتحقيق أفضل أداء. about:tracing
عرض Chrome هو أداة قيّمة للحصول على إحصاءات حول ما يفعله الرمز البرمجي في الواقع، وسيساعدك في زيادة وقت التطوير إلى أقصى حد من خلال معالجة المشاكل المناسبة.
ما هي الخطوات التالية؟
بالإضافة إلى وحدة معالجة الرسومات، يمكنك أيضًا تتبُّع أجزاء أخرى من وقت تشغيل Chrome. تم تجهيز Chrome Canary، وهو إصدار Chrome في المرحلة المبكرة، لتتبُّع عمليات I/O وIndexedDB والعديد من الأنشطة الأخرى. عليك قراءة هذه المقالة حول Chromium لفهم الحالة الحالية لأحداث التتبّع بشكل أفضل.
إذا كنت من مطوّري ألعاب الويب، يُرجى مشاهدة الفيديو أدناه. يعرض هذا الفيديو عرضًا تقديميًا من فريق "مناصرة مطوّري الألعاب" في Google في مؤتمر GDC لعام 2012 حول تحسين أداء ألعاب Chrome: