تحليل بدء تشغيل التطبيق وتحسينه

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

وننصح باستخدام مكتبة "مقياس الأداء الفائق" لقياس بدء التشغيل. توفّر المكتبة نظرة عامة وتتبعات تفصيلية للنظام لمعرفة ما يحدث بالضبط أثناء بدء التشغيل.

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

لتحليل بدء تشغيل تطبيقك، عليك إجراء ما يلي:

خطوات تحليل تجربة بدء التشغيل وتحسينها

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

لإجراء مُفاضلات بشأن الأداء، يجب مراعاة ما يلي:

  • استخدِم مكتبة مقاييس الأداء الكلية لقياس الوقت الذي تستغرقه كل عملية وتحديد الأجزاء التي يستغرق إكمالها وقتًا طويلاً.

  • تأكَّد من أنّ العملية التي تستهلك قدرًا كبيرًا من الموارد أمر بالغ الأهمية لبدء تشغيل التطبيق. إذا تمكنت العملية من الانتظار حتى يتم رسم التطبيق بالكامل، فيمكن أن تساعد في تقليل قيود الموارد عند بدء التشغيل.

  • تأكَّد من أنك تتوقع تنفيذ هذه العملية عند بدء تشغيل التطبيق. في كثير من الأحيان، يمكن استدعاء عمليات غير ضرورية من التعليمات البرمجية القديمة أو مكتبات الجهات الخارجية.

  • نقل العمليات طويلة المدى إلى الخلفية، إن أمكن قد تؤثر العمليات في الخلفية في استخدام وحدة المعالجة المركزية (CPU) أثناء بدء التشغيل.

وبعد التحقيق الكامل في العملية، يمكنك تحديد المفاضلة بين الوقت الذي يستغرقه التحميل وضرورة تضمينه في بدء تشغيل التطبيق. تذكر تضمين احتمالية التراجع أو كسر التغييرات عند تغيير سير عمل التطبيق.

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

قياس وتحليل الوقت المستغرق في العمليات الرئيسية

عند إكمال عملية تتبُّع بدء تشغيل التطبيق، يمكنك الاطّلاع على بيانات التتبُّع وقياس الوقت المستغرق في العمليات الرئيسية مثل bindApplication أو activityStart. ننصحك باستخدام Perfetto أو Android Studio Profilers لتحليل عمليات التتبّع هذه.

انظر إلى إجمالي الوقت المستغرق أثناء بدء تشغيل التطبيق لتحديد أي عمليات تؤدي إلى ما يلي:

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

تحقَّق من كل مصدر من هذه الآثار بشكل أكبر للعثور على الفجوات في الأداء.

تحديد العمليات المكلفة في سلسلة التعليمات الرئيسية

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

Kotlin

class MyApplication : Application() {

    override fun onCreate() {
        super.onCreate()

        ...
        if (BuildConfig.DEBUG)
            StrictMode.setThreadPolicy(
                StrictMode.ThreadPolicy.Builder()
                    .detectAll()
                    .penaltyDeath()
                    .build()
            )
        ...
    }
}

Java

public class MyApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();

        ...
        if(BuildConfig.DEBUG) {
            StrictMode.setThreadPolicy(
                    new StrictMode.ThreadPolicy.Builder()
                            .detectAll()
                            .penaltyDeath()
                            .build()
            );
        }
        ...
    }
}

ويؤدي استخدام StrictMode.ThreadPolicy إلى تفعيل سياسة سلاسل المحادثات في جميع إصدارات تصحيح الأخطاء، وتعطُّل التطبيق عند رصد انتهاكات لسياسة سلاسل المحادثات، ما يصعِّب تفويت انتهاكات سياسة سلاسل المحادثات.

TTID وTTFD

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

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

لذا، نقترح عليك تحسين كل من تقنية TTID وTTFD، لأنّ كلاً منها مهم في منطقته الخاصة. يساعد تقنية TTID القصيرة المستخدم في معرفة أن التطبيق يتم تشغيله بالفعل. من المهم الحفاظ على قصر TTFD للمساعدة في ضمان بدء المستخدم للتفاعل مع التطبيق بسرعة.

تحليل الحالة العامة لسلسلة المحادثات

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

توفّر أدوات مثل Android Studio Profiler وPerfetto نظرة عامة مفصّلة حول سلسلة المحادثات الرئيسية والوقت المستغرق في كل مرحلة. لمزيد من المعلومات حول تمثيل مرئيات لعمليات تتبُّع الأداء، يُرجى الاطّلاع على مستندات Perfetto UI.

تحديد الأجزاء الرئيسية لحالة سكون سلسلة التعليمات الرئيسية

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

تقليل حظر سلسلة التعليمات الرئيسية والنوم غير المتقطع

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

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

تحسين وقت بدء التشغيل

بعد تحديد فرصة للتحسين، استكشف الحلول الممكنة للمساعدة في تحسين أوقات بدء التشغيل:

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

تحليل أداء واجهة المستخدم

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

تقييد العمل عند الإعداد

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

لتحسين الإعداد، اتّبِع الخطوات التالية:

  • امنح الأولوية لتمريرات التخطيط البطيئة واختَر هذه البطاقات لتحسينها.
  • تحقّق من كل تحذير من Perfetto وتنبيه من Systrace عن طريق إضافة أحداث تتبُّع مخصّصة لتقليل عمليات السحب والتأخير المكلفة.

قياس بيانات الإطار

هناك طرق متعددة لقياس بيانات الإطار. إن طرق الجمع الخمس الرئيسية هي:

  • جمع البيانات على الجهاز باستخدام dumpsys gfxinfo: ليست كل الإطارات التي تتم ملاحظتها في بيانات dumpsys مسؤولة عن بطء العرض للتطبيق أو يكون لها أي تأثير في المستخدمين النهائيين. ومع ذلك، يعد هذا مقياسًا جيدًا للنظر فيه عبر دورات الإصدار المختلفة لفهم الاتجاه العام للأداء. لمعرفة المزيد من المعلومات حول استخدام gfxinfo وframestats لدمج قياسات أداء واجهة المستخدم في ممارسات الاختبار، يمكنك الاطّلاع على أساسيات اختبار تطبيقات Android.
  • جمع الحقول باستخدام JankStats: يمكنك جمع أوقات عرض الإطارات من أجزاء معيّنة من تطبيقك من خلال مكتبة JankStats وتسجيل البيانات وتحليلها.
  • في الاختبارات التي تستخدم مقياس أداء ماكرو (Perfetto الخيارات المتقدمة)
  • Perfetto FrameTimeline: في نظام التشغيل Android 12 (المستوى 31 من واجهة برمجة التطبيقات)، يمكنك جمع مقاييس المخطط الزمني للإطار من سجلّ Perfetto الذي يؤدي العمل إليه إلى انخفاض الإطار. يمكن أن تكون هذه هي الخطوة الأولى لتشخيص سبب إسقاط الإطارات.
  • أداة تحليل البيانات في "استوديو Android" لرصد البيانات غير المرغوب فيها

الاطّلاع على وقت تحميل النشاط الرئيسي

قد يحتوي النشاط الرئيسي لتطبيقك على كمية كبيرة من المعلومات التي يتم تحميلها من مصادر متعددة. تحقَّق من تنسيق Activity للمنزل، واطّلِع على وجه التحديد على طريقة Choreographer.onDraw لالنشاط المنزلي.

  • استخدِم reportFullyDrawn لإبلاغ النظام بأنّ تطبيقك قد تم رسمه بالكامل لأغراض التحسين.
  • يمكنك قياس النشاط وعمليات إطلاق التطبيقات باستخدام أداة StartupTimingMetric من خلال مكتبة مقاييس الأداء الشاملة.
  • انظر إلى حجم الإطارات.
  • حدد التخطيطات التي تستغرق وقتًا طويلاً للعرض أو القياس.
  • حدِّد مواد العرض التي تستغرِق وقتًا طويلاً للتحميل.
  • حدد التخطيطات غير الضرورية التي يتم تضخيمها أثناء بدء التشغيل.

ضع في اعتبارك هذه الحلول الممكنة لتحسين وقت تحميل النشاط الرئيسي:

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

    إذا كنت تستخدم Jetpack Compose، يمكنك اتّباع سلوك مشابه لـ ViewStub باستخدام الحالة لتأجيل تحميل بعض المكونات:

    var shouldLoad by remember {mutableStateOf(false)}
    
    if (shouldLoad) {
     MyComposable()
    }
    

    تحميل العناصر القابلة للتعديل داخل المجموعة الشرطية عن طريق تعديل shouldLoad:

    LaunchedEffect(Unit) {
     shouldLoad = true
    }
    

    يؤدي هذا إلى تشغيل إعادة تركيب تتضمن التعليمة البرمجية داخل الكتلة الشرطية في المقتطف الأول.