تصحيح أخطاء الملفات الشخصية المرجعية

يعرض هذا المستند أفضل الممارسات للمساعدة في تشخيص المشاكل والتأكّد من أنّ ملفاتك الشخصية الأساسية تعمل بشكل صحيح لتحقيق أكبر استفادة.

مشاكل الإنشاء

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

./gradlew assembleDemoRelease
Starting a Gradle Daemon (subsequent builds will be faster)
Calculating task graph as no configuration cache is available for tasks: assembleDemoRelease
Type-safe project accessors is an incubating feature.

> Task :benchmarks:pixel6Api33DemoNonMinifiedReleaseAndroidTest
Starting 14 tests on pixel6Api33

com.google.samples.apps.nowinandroid.foryou.ScrollForYouFeedBenchmark > scrollFeedCompilationNone[pixel6Api33] FAILED
        java.lang.AssertionError: ERRORS (not suppressed): EMULATOR
        WARNINGS (suppressed):
        ...

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

installDemoRelease -Pandroid.testInstrumentationRunnerArguments.androidx.benchmark.enabledRules=BaselineProfile

بدلاً من ذلك، يمكنك إنشاء إعداد تشغيل مخصّص في Android Studio ل تفعيل الملفات الشخصية الأساسية على المحاكيات من خلال اختيار تشغيل > تعديل الإعدادات:

إضافة إعداد تشغيل مخصّص لإنشاء الملفات الشخصية الأساسية في ميزة "الآن" في Android
الشكل 1. أضِف إعداد تشغيل مخصّصًا لإنشاء ملف تعريفي أساسي في ميزة "الآن" على Android.

مشاكل التثبيت

تأكَّد من أنّ حِزمة APK أو حِزمة AAB التي تفحصها من أحد أنواع الإصدارات التي تتضمن الملفات الشخصية الأساسية:

  1. في Android Studio، اختَر الإنشاء > تحليل APK.
  2. افتح حزمة AAB أو حزمة APK.
  3. إذا كنت تفحص حزمة تطبيق مُعدّة للنشر على جميع الأجهزة، يكون الملف الشخصي في القسم /BUNDLE-METADATA/com.android.tools.build.profiles/baseline.prof. إذا كنت بصدد فحص حزمة APK، يمكنك العثور على الملف الشخصي في /assets/dexopt/baseline.prof.
البحث عن ملف تعريف أساسي باستخدام "عارض حِزم APK" في "استوديو Android"
الشكل 2. تحقّق من توفّر ملف تعريف أساسي باستخدام "عارض حِزم APK" في "استوديو Android".

يجب تجميع الملفات الشخصية الأساسية على الجهاز الذي يعمل عليه التطبيق. عند تثبيت التطبيق باستخدام "متجر Play" أو Android Studio أو أداة سطر أوامر Gradle Wrapper ، يتم التجميع على الجهاز تلقائيًا. عند تثبيت التطبيق باستخدام أدوات أخرى، تكون مكتبة ProfileInstaller في Jetpack مسؤولة عن إضافة الملفات إلى "قائمة الانتظار" لتجميعها أثناء عملية تحسين DEX التالية في الخلفية. في هذه الحالات، إذا كنت تريد التأكّد من استخدام الملفات التجارية الأساسية، قد تحتاج إلى فرض تجميع الملفات التجارية الأساسية. يتيح لك ProfileVerifier الاستعلام عن حالة تثبيت الملف الشخصي وتجميعه، كما هو موضّح في المثال التالي:

Kotlin

private const val TAG = "MainActivity"

class MainActivity : ComponentActivity() {
  ...
  override fun onResume() {
    super.onResume()
    lifecycleScope.launch {
      logCompilationStatus()
    }
  }

  private suspend fun logCompilationStatus() {
     withContext(Dispatchers.IO) {
        val status = ProfileVerifier.getCompilationStatusAsync().await()
        when (status.profileInstallResultCode) {
            RESULT_CODE_NO_PROFILE ->
                Log.d(TAG, "ProfileInstaller: Baseline Profile not found")
            RESULT_CODE_COMPILED_WITH_PROFILE ->
                Log.d(TAG, "ProfileInstaller: Compiled with profile")
            RESULT_CODE_PROFILE_ENQUEUED_FOR_COMPILATION ->
                Log.d(TAG, "ProfileInstaller: Enqueued for compilation")
            RESULT_CODE_COMPILED_WITH_PROFILE_NON_MATCHING ->
                Log.d(TAG, "ProfileInstaller: App was installed through Play store")
            RESULT_CODE_ERROR_PACKAGE_NAME_DOES_NOT_EXIST ->
                Log.d(TAG, "ProfileInstaller: PackageName not found")
            RESULT_CODE_ERROR_CACHE_FILE_EXISTS_BUT_CANNOT_BE_READ ->
                Log.d(TAG, "ProfileInstaller: Cache file exists but cannot be read")
            RESULT_CODE_ERROR_CANT_WRITE_PROFILE_VERIFICATION_RESULT_CACHE_FILE ->
                Log.d(TAG, "ProfileInstaller: Can't write cache file")
            RESULT_CODE_ERROR_UNSUPPORTED_API_VERSION ->
                Log.d(TAG, "ProfileInstaller: Enqueued for compilation")
            else ->
                Log.d(TAG, "ProfileInstaller: Profile not compiled or enqueued")
        }
    }
}

Java

public class MainActivity extends ComponentActivity {

    private static final String TAG = "MainActivity";

    @Override
    protected void onResume() {
        super.onResume();

        logCompilationStatus();
    }

    private void logCompilationStatus() {
         ListeningExecutorService service = MoreExecutors.listeningDecorator(
                Executors.newSingleThreadExecutor());
        ListenableFuture<ProfileVerifier.CompilationStatus> future =
                ProfileVerifier.getCompilationStatusAsync();
        Futures.addCallback(future, new FutureCallback<>() {
            @Override
            public void onSuccess(CompilationStatus result) {
                int resultCode = result.getProfileInstallResultCode();
                if (resultCode == RESULT_CODE_NO_PROFILE) {
                    Log.d(TAG, "ProfileInstaller: Baseline Profile not found");
                } else if (resultCode == RESULT_CODE_COMPILED_WITH_PROFILE) {
                    Log.d(TAG, "ProfileInstaller: Compiled with profile");
                } else if (resultCode == RESULT_CODE_PROFILE_ENQUEUED_FOR_COMPILATION) {
                    Log.d(TAG, "ProfileInstaller: Enqueued for compilation");
                } else if (resultCode == RESULT_CODE_COMPILED_WITH_PROFILE_NON_MATCHING) {
                    Log.d(TAG, "ProfileInstaller: App was installed through Play store");
                } else if (resultCode == RESULT_CODE_ERROR_PACKAGE_NAME_DOES_NOT_EXIST) {
                    Log.d(TAG, "ProfileInstaller: PackageName not found");
                } else if (resultCode == RESULT_CODE_ERROR_CACHE_FILE_EXISTS_BUT_CANNOT_BE_READ) {
                    Log.d(TAG, "ProfileInstaller: Cache file exists but cannot be read");
                } else if (resultCode
                        == RESULT_CODE_ERROR_CANT_WRITE_PROFILE_VERIFICATION_RESULT_CACHE_FILE) {
                    Log.d(TAG, "ProfileInstaller: Can't write cache file");
                } else if (resultCode == RESULT_CODE_ERROR_UNSUPPORTED_API_VERSION) {
                    Log.d(TAG, "ProfileInstaller: Enqueued for compilation");
                } else {
                    Log.d(TAG, "ProfileInstaller: Profile not compiled or enqueued");
                }
            }

            @Override
            public void onFailure(Throwable t) {
                Log.d(TAG,
                        "ProfileInstaller: Error getting installation status: " + t.getMessage());
            }
        }, service);
    }
}

تقدّم رموز النتائج التالية تلميحات عن سبب بعض المشاكل:

RESULT_CODE_COMPILED_WITH_PROFILE
يتم تثبيت الملف الشخصي وتجميعه واستخدامه عند تشغيل التطبيق. وهذه هي النتيجة التي تريد رؤيتها.
RESULT_CODE_ERROR_NO_PROFILE_EMBEDDED
لم يتم العثور على أي ملف شخصي في حزمة APK التي يتم تشغيلها. تأكَّد من استخدام إصدار معدّل يتضمّن الملفات الشخصية الأساسية في حال ظهور هذا الخطأ، ومن أنّ حزمة APK تحتوي على ملف شخصي.
RESULT_CODE_NO_PROFILE
لم يتم تثبيت أي ملف شخصي لهذا التطبيق عند تثبيته من خلال متجر التطبيقات أو مدير الحِزم. السبب الرئيسي لظهور رمز الخطأ هذا هو عدم تشغيل ملف بدء التثبيت بسبب إيقاف ProfileInstallerInitializer. يُرجى العلم أنّه عند الإبلاغ عن هذا الخطأ، لا يزال يتم العثور على ملف تعريف مضمّن في APK التطبيق. عندما لا يتم العثور على ملف تعريف مضمّن، يكون رمز الخطأ الذي يتم إرجاعه هو RESULT_CODE_ERROR_NO_PROFILE_EMBEDDED.
RESULT_CODE_PROFILE_ENQUEUED_FOR_COMPILATION
يتم العثور على ملف تعريف في حزمة APK أو حزمة AAB ويتم وضعه في قائمة الانتظار لتجميعه. عندما تثبِّت أداة ProfileInstaller أحد الملفات الشخصية، يتم وضعه في قائمة الانتظار لتجميعه في المرة التالية التي يُجري فيها النظام عملية تحسين رمز DEX في الخلفية. لا يكون الملف الشخصي فعالًا حتى تكتمل عملية التجميع. لا تحاول قياس أداء "ملف الأداء الأساسي" ملفاتك الشخصية إلى أن تكتمل عملية التجميع. قد تحتاج إلى فرض تجميع الملفات التجارية الأساسية. لن يحدث هذا الخطأ عند تثبيت التطبيق من متجر التطبيقات أو من مدير الحِزم على الأجهزة التي تعمل بالإصدار 9 من Android (الإصدار 28 من حزمة تطوير البرامج) والإصدارات الأحدث، لأنّ عملية الترجمة تتم أثناء التثبيت.
RESULT_CODE_COMPILED_WITH_PROFILE_NON_MATCHING
تم تثبيت ملف شخصي غير مطابق وتم تجميع التطبيق باستخدامه. هذه هي نتيجة التثبيت من خلال "متجر Google Play" أو مدير الحِزم. يُرجى العلم أنّ هذه النتيجة تختلف عن RESULT_CODE_COMPILED_WITH_PROFILE لأنّه لن يتم تجميع سوى أي طرق لا تزال مشترَكة بين الملف الشخصي والتطبيق في الملف الشخصي غير المطابق. ويكون الملف الشخصي أصغر مما هو متوقّع، وسيتم تجميع عدد طرق أقل من تلك المضمّنة في الملف الشخصي الأساسي.
RESULT_CODE_ERROR_CANT_WRITE_PROFILE_VERIFICATION_RESULT_CACHE_FILE
لا يمكن لـ
ProfileVerifier كتابة ملف ذاكرة التخزين المؤقت لنتيجة إثبات الملكية. يمكن أن يحدث ذلك إما بسبب خطأ في أذونات مجلد التطبيق أو في حال عدم توفّر مساحة فارغة كافية على القرص في الجهاز.
RESULT_CODE_ERROR_UNSUPPORTED_API_VERSION
لا يتيح
ProfileVerifieris running on an unsupported API version of Android. ProfileVerifier سوى الإصدار 9 من نظام التشغيل Android (المستوى 28 من واجهة برمجة التطبيقات) والإصدارات الأحدث.
RESULT_CODE_ERROR_PACKAGE_NAME_DOES_NOT_EXIST
يتم طرح PackageManager.NameNotFoundException عند طلب PackageManager لحزمة التطبيق. من المفترض ألا يحدث ذلك إلا نادرًا. جرِّب إلغاء تثبيت التطبيق وإعادة تثبيت كل شيء.
RESULT_CODE_ERROR_CACHE_FILE_EXISTS_BUT_CANNOT_BE_READ
يتوفّر ملف ذاكرة تخزين مؤقت لنتيجة إثبات الملكية السابقة، ولكن لا يمكن قراءته. من المفترض أن يحدث ذلك نادرًا. جرِّب إلغاء تثبيت التطبيق وإعادة تثبيت كل شيء.

استخدام ProfileVerifier في مرحلة الإنتاج

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

فرض تجميع الملفات التجارية الأساسية

إذا كانت حالة تجميع الملفات الشخصية للمرجع هي RESULT_CODE_PROFILE_ENQUEUED_FOR_COMPILATION، يمكنك فرض التجميع العميق فورًا باستخدام adb:

adb shell cmd package compile -r bg-dexopt PACKAGE_NAME

التحقّق من حالة الترجمة بدون ProfileVerifier

إذا لم تكن تستخدم ProfileVerifier، يمكنك التحقّق من حالة الترجمة باستخدام adb، على الرغم من أنّه لا يوفّر إحصاءات مفصّلة مثل ProfileVerifier:

adb shell dumpsys package dexopt | grep -A 2 PACKAGE_NAME

يؤدي استخدام adb إلى ظهور نتيجة مشابهة لما يلي:

  [com.google.samples.apps.nowinandroid.demo]
    path: /data/app/~~dzJiGMKvp22vi2SsvfjkrQ==/com.google.samples.apps.nowinandroid.demo-7FR1sdJ8ZTy7eCLwAnn0Vg==/base.apk
      arm64: [status=speed-profile] [reason=bg-dexopt] [primary-abi]
        [location is /data/app/~~dzJiGMKvp22vi2SsvfjkrQ==/com.google.samples.apps.nowinandroid.demo-7FR1sdJ8ZTy7eCLwAnn0Vg==/oat/arm64/base.odex]

تشير قيمة الحالة إلى حالة تجميع الملف الشخصي، وهي إحدى القيم التالية:

حالة التجميع المعنى
speed‑profile توفُّر ملف تجاري مجمَّع واستخدامه
verify لا يتوفّر ملف شخصي مجمّع.

لا تعني الحالة verify أنّ حزمة APK أو حزمة تطبيق بتنسيق AAB لا تحتويان على ملف شخصي، لأنّه يمكن وضعهما في قائمة الانتظار لتجميعهما من خلال مهمة تحسين DEX التالية في الخلفية.

تشير قيمة السبب إلى ما يؤدي إلى تجميع الملف الشخصي، وهي إحدى القيم التالية:

السبب المعنى
install‑dm تم تجميع ملف قاعدة بيانات يدويًا أو من خلال Google Play عند تثبيت التطبيق.
bg‑dexopt تم تجميع ملف شخصي عندما كان جهازك غير نشِط. قد يكون هذا الملف الشخصي هو ملف قاعدة بيانات أو قد يكونملفًا تم جمعه أثناء استخدام التطبيق.
cmdline تم تشغيل عملية التجميع باستخدام adb. قد يكون هذا الملف الشخصي هو ملف قاعدة بيانات أو قد يكونملفًا شخصيًا تم جمعه أثناء استخدام التطبيق.

مشاكل في الأداء

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

قياس أداء مقاييس بدء التشغيل بشكل صحيح

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

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

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

يجب إبقاء كلّ من TTID وTTFD منخفضَين قدر الإمكان لجعل تطبيقك سريع الاستجابة.

يمكن للنظام رصد TTID وعرضه في Logcat والإبلاغ عنه كجزء من قياسات أداء بدء التشغيل. ومع ذلك، لا يمكن للنظام تحديد وقت الاستجابة للتفاعل، ويكون على التطبيق الإبلاغ عن ذلك عند وصوله إلى حالة تفاعلية مرسومة بالكامل. يمكنك إجراء ذلك من خلال استدعاء reportFullyDrawn() أو ReportDrawn إذا كنت تستخدم Jetpack Compose. إذا كانت لديك عدة tasks في الخلفية يجب إكمالها كلها قبل اعتبار التطبيق مكتملًا ، يمكنك استخدام FullyDrawnReporter، كما هو موضّح في تحسين دقة توقيت بدء التشغيل.

الملفات الشخصية للمكتبة والملفات الشخصية المخصّصة

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

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

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

Kotlin

android {
  ...
  buildTypes {
    ...
    // Release build with only library profiles.
    create("releaseWithoutCustomProfile") {
      initWith(release)
    }
    ...
  }
  ...
}
...
dependencies {
  ...
  // Remove the baselineProfile dependency.
  // baselineProfile(project(":baselineprofile"))
}

baselineProfile {
  variants {
    create("release") {
      from(project(":baselineprofile"))
    }
  }
}

رائع

android {
  ...
  buildTypes {
    ...
    // Release build with only library profiles.
    releaseWithoutCustomProfile {
      initWith(release)
    }
    ...
  }
  ...
}
...
dependencies {
  ...
  // Remove the baselineProfile dependency.
  // baselineProfile ':baselineprofile"'
}

baselineProfile {
  variants {
    release {
      from(project(":baselineprofile"))
    }
  }
}

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

عليك أيضًا إضافة السعر المتغير الجديد إلى وحدة إنشاء الملفات التجارية. في هذا المثال، تم تسمية وحدة المنتج :baselineprofile.

Kotlin

android {
  ...
    buildTypes {
      ...
      // Release build with only library profiles.
      create("releaseWithoutCustomProfile") {}
      ...
    }
  ...
}

رائع

android {
  ...
    buildTypes {
      ...
      // Release build with only library profiles.
      releaseWithoutCustomProfile {}
      ...
    }
  ...
}

عند تشغيل مقياس الأداء من "استوديو Android"، اختَر أحد الصيغ التالية: releaseWithoutCustomProfile لقياس الأداء باستخدام ملفات ملفّات الشخصية المكتبة فقط، أو اختَر release لقياس الأداء باستخدام ملفات ملفّات الشخصية المكتبة والملفات الشخصية المخصّصة.

تجنُّب بدء تشغيل التطبيق أثناء عمليات الإدخال/الإخراج

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

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

إذا كان تطبيقك يستخدم Hilt، يمكنك توفير تنفيذات وهمية مرتبطة بعمليات الإدخال/الإخراج عند إجراء اختبارات الأداء في اختبارات الأداء الدقيقة وHilt.

أن تشمل جميع رحلات المستخدمين المهمة

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