دراسة حالة: كيفية مساهمة فريق Gmail Wear OS في تحسين عملية بدء تشغيل تطبيقاتهم بنسبة %50

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

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

تسجيل آثار الأنشطة والنظر في صفحة بدء تشغيل التطبيق

لبدء عملية التحليل، يمكنك التقاط تتبُّع يتضمّن بدء تشغيل التطبيق لفحصه عن كثب في Perfetto أو Android Studio. تستخدم دراسة الحالة هذه Perfetto لأنها تُظهر لك ما يحدث عبر نظام الأجهزة، خارج نطاق تطبيقك. عند تحميل آثار التتبع في Perfetto، يبدو الأمر على النحو التالي:

الشكل 1. العرض الأولي للتتبُّع في Perfetto.

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

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

يُرجى العِلم أنّ مقياس بدء تطبيقات Android يمثّل الوقت المُستغرَق للعرض الأولي، حتى إذا كنت تستخدم reportFullyDrawn(). لتحديد وقت العرض الكامل، ابحث عن reportFullyDrawn() في مربّع بحث Perfetto.

التحقّق من سلسلة التعليمات الرئيسية

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

للعثور على سلسلة التعليمات الرئيسية، ابحث عن الصف الذي يحتوي على اسم حزمة تطبيقك وقم بتوسيعه. الصفان اللذان يحملان نفس اسم الحزمة (عادةً أول صفين في القسم) يمثلان سلسلة التعليمات الرئيسية. من بين صفي سلسلة التعليمات الرئيسيين، يمثل الصف الأول حالة وحدة المعالجة المركزية والصف الثاني يمثل نقاط التتبع. ثبِّت صفَّي سلسلة المحادثات الرئيسيتَين أسفل مقياس الشركات الناشئة في تطبيقات Android.

تم تثبيت عمليات بدء تطبيقات Android وصفوف سلاسل المحادثات الرئيسية.
الشكل 3. ثبِّت صفوف سلسلة المحادثات الرئيسية أسفل المقياس المخصّص للشركات الناشئة في تطبيقات Android للمساعدة في التحليل.

الوقت المنقضي في حالة قابلة للتنفيذ وتزايد الطلب على وحدة المعالجة المركزية (CPU)

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

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

يتم تمييز سلسلة التعليمات الرئيسية بالوقت الإجمالي في حالات مختلفة في لوحة "حالات سلسلة المحادثات".
الشكل 4. يمكنك تقييم الوقت النسبي بالحالات من Runnable إلى Running للحصول على فكرة أولية عن مقدار تزايد الطلب على وحدة المعالجة المركزية (CPU).

وكلما ارتفعت نسبة الوقت في الحالة Runnable إلى الوقت في Running، زاد احتمال حدوث تزايد في الأداء على وحدة المعالجة المركزية (CPU). عند فحص مشاكل الأداء بهذه الطريقة، ركِّز على الإطار الأطول أولاً ثم اعمَل على الإطارات الأصغر.

عند تحليل الوقت المستغرق في حالة Runnable، يجب مراعاة مكونات الجهاز. بما أنّ التطبيق المصوَّر يعمل على جهاز قابل للارتداء مزوَّد بوحدة معالجة مركزية (CPU)، من المتوقع زيادة الوقت الذي نقضيه في حالة Runnable وزيادة التنافس على وحدة المعالجة المركزية (CPU) مع العمليات الأخرى مقارنةً بالأجهزة التي تحتوي على المزيد من وحدات المعالجة المركزية (CPU). على الرغم من أنّه يتم استخدام حالة Runnable لفترة أطول من المتوقّع لتطبيق هاتف عادي، إلا أنّ ذلك قد يكون مفهومًا في سياق الأجهزة القابلة للارتداء.

الوقت الذي قضيته في "OpenDexFilesFromOat*"

تحقَّق الآن من الوقت المُستغرَق في OpenDexFilesFromOat*، أي في عملية التتبُّع، يحدث في الوقت نفسه الذي تم فيه استخدام شريحة bindApplication. تمثل هذه الشريحة الوقت المستغرق لقراءة ملفات DEX للتطبيق.

معاملات الصنف المحظور

بعد ذلك، تحقَّق من معاملات الصنف. تمثّل معاملات الصنف Binder الطلبات التي تتم بين العميل والخادم: في هذه الحالة، يستدعي التطبيق (العميل) نظام Android (الخادم) باستخدام binder transaction، ويستجيب الخادم باستخدام binder reply. يُرجى التأكّد من أنّ التطبيق لا يُجري معاملات ربط غير ضرورية أثناء بدء التشغيل، لأنّها تزيد من خطر الزيادة في استخدام وحدة المعالجة المركزية (CPU). إذا كان بإمكانك، يمكنك تأجيل العمل الذي يتضمن استدعاءات الصنف Binder بعد فترة بدء تشغيل التطبيق. إذا اضطررت إلى إجراء معاملات الصنف، احرص على ألا تستغرق وقتًا أطول من معدّل تحديث Vsync على جهازك.

عادةً ما تتم معاملة الصنف الأولى في الوقت نفسه مع شريحة ActivityThreadMain، وهي طويلة جدًا في هذه الحالة. لمعرفة المزيد حول ما قد يحدث، اتّبِع الخطوات التالية:

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

    يربط خط الصنف بين طلب الصنف والرد.
    الشكل 5. يمكنك تحديد معاملات الصنف التي تتم أثناء بدء تشغيل التطبيق وتقييم ما إذا كان بإمكانك تأجيلها.
  3. لمعرفة كيف يعالج خادم النظام معاملة الصنف هذا، ثبِّت سلسلتَي Cpu 0 وCpu 1 في أعلى الشاشة.

  4. ابحث عن عمليات النظام التي تعالج ردّ الصنف من خلال البحث عن الشرائح التي تتضمّن اسم سلسلة ردّ المصنف، في هذه الحالة "بينer:687_11 [2542]". انقر فوق عمليات النظام ذات الصلة للحصول على مزيد من المعلومات حول معاملة الصنف.

ألقِ نظرة على عملية النظام التالية المرتبطة بمعاملة الصنف ذات الصلة التي تحدث على وحدة المعالجة المركزية 0 (CPU):

معالجة النظام مع الحالة النهائية "قابلة للتشغيل (مستقلة).
الشكل 6. عملية النظام في الحالة Runnable (Preempted)، ما يشير إلى أنّها تتأخر.

تعرض حالة الانتهاء عبارة Runnable (Preempted)، ما يعني أنّ العملية تتأخر بسبب عمل وحدة المعالجة المركزية (CPU) بطريقة أخرى. لمعرفة العوامل التي يتم الاستعداد لها، عليك توسيع صفوف أحداث Ftrace. في علامة التبويب أحداث Ftrace التي أصبحت متاحة، انتقِل للأسفل وابحث عن الأحداث ذات الصلة بسلسلة محادثات المجلّد التي تهمّك "بادئ وهي:687_11 [2542]". في الوقت تقريبًا الذي يتم فيه بدء عملية النظام، حدث حدثان لخادم النظام يتضمنان الوسيطة "decon"، ما يعني أنهما مرتبطان بوحدة تحكم الشاشة. يبدو هذا معقولاً لأن وحدة التحكم في العرض تضع الإطارات على الشاشة - مهمة مهمة! اترك الأحداث كما هي بعد ذلك.

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

نشاط التجميع أثناء التشغيل (JIT)

لفحص نشاط التجميع في الوقت المناسب (JIT)، وسِّع العمليات الخاصة بتطبيقك وابحث عن صفَّي "مجموعة سلاسل JIT" وثبِّتهما في أعلى العرض. بما أنّ هذا التطبيق يستفيد من الملفات الشخصية الأساسية أثناء بدء تشغيل التطبيق، يحدث نشاط JIT القليل جدًا من الأنشطة حتى يتم رسم الإطار الأول، ويشار إليه بنهاية مكالمة Choreographer.doFrame الأولى. مع ذلك، يُرجى ملاحظة سبب بطء البدء JIT compiling void، والذي يشير إلى أنّ نشاط النظام الذي يحدث أثناء نقطة التتبع المُصنَّفة Application creation يتسبب في الكثير من نشاط التجميع أثناء التشغيل (JIT) في الخلفية. لحل هذه المشكلة، أضِف الأحداث التي تحدث بعد وقت قصير من رسم الإطار الأول إلى الملف الشخصي الأساسي من خلال توسيع مجموعة الملفات الشخصية إلى نقطة يكون فيها التطبيق جاهزًا للاستخدام. وفي كثير من الحالات، يمكنك إجراء ذلك عن طريق إضافة سطر إلى نهاية مجموعة "الملف الشخصي الأساسي" اختبار "مقياس الأداء العام" الذي ينتظر ظهور تطبيق مصغّر لواجهة مستخدم معيّن على شاشتك، ما يشير إلى أنّ الشاشة ممتلئة بالكامل.

مجموعات خيط Jit مع تمييز شريحة "Jit comcriting إعلان".
الشكل 8. إذا لاحظت الكثير من أنشطة JIT، ننصحك بتوسيع ملفك الشخصي الأساسي إلى أن يصبح التطبيق جاهزًا للاستخدام.

النتائج

نتيجةً لهذا التحليل، أجرى فريق Gmail Wear OS التحسينات التالية:

  • نظرًا لأن الفريق لاحظ وجود تزاحم أثناء بدء تشغيل التطبيق عند الاطّلاع على نشاط وحدة المعالجة المركزية (CPU)، استبدلوا الصورة المتحركة الدوّارة المستخدمة للإشارة إلى أنّ التطبيق يتم تحميله بصورة ثابتة واحدة. وتعمل أيضًا على إطالة شاشة البداية لتأجيل حالة لمعان الشاشة، وتُستخدم حالة الشاشة الثانية للإشارة إلى تحميل التطبيق، وذلك بهدف إخلاء موارد وحدة المعالجة المركزية (CPU). أدى ذلك إلى تحسين وقت استجابة بدء تشغيل التطبيق بنسبة %50.
  • من خلال الاطّلاع على الوقت المستغرَق في OpenDexFilesFromOat* ونشاط JIT، فعّلت الشركة R8 لإعادة كتابة الملفات الشخصية المرجعية. وأدى ذلك إلى تحسين وقت استجابة بدء تشغيل التطبيق بنسبة %20.

في ما يلي بعض النصائح من الفريق حول كيفية تحليل أداء التطبيق بكفاءة:

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

لمزيد من المعلومات، اطّلِع على المراجع التالية: