يعرض هذا المستند أفضل الممارسات للمساعدة في تشخيص المشاكل والتأكّد من أنّ ملفاتك الشخصية الأساسية تعمل بشكل صحيح لتحقيق أكبر استفادة.
مشاكل الإنشاء
إذا نسخت مثال الملفات الشخصية الأساسية في تطبيق الميزات المتوفّرة الآن في 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 ل تفعيل الملفات الشخصية الأساسية على المحاكيات من خلال اختيار تشغيل > تعديل الإعدادات:

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

يجب تجميع الملفات الشخصية الأساسية على الجهاز الذي يعمل عليه التطبيق. عند
تثبيت التطبيق باستخدام "متجر 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
لا يتيح - ProfileVerifier
is 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.
أن تشمل جميع رحلات المستخدمين المهمة
من المهمّ تغطية جميع تجارب المستخدِمين المهمة بدقّة في عملية إنشاء الملف الشخصي الأساسي. ولن تؤدي ميزة "الملفات الشخصية الأساسية" إلى تحسين أيّ من رحلات المستخدِمين التي لا يتمّ تضمينها. تشمل الملفات الشخصية الأساسية الأكثر فعالية جميع تجارب المستخدمين الشائعة في بدء التشغيل، بالإضافة إلى تجارب المستخدمين الحسّاسة للأداء داخل التطبيق، مثل الانتقال في القوائم.