إنشاء الملفات المرجعية الأساسية وقياسها يدويًا

ننصحك بشدة بأتمتة عملية إنشاء قواعد الملفات الشخصية باستخدام مكتبة Jetpack Macrobenchmark للحدّ من الجهد اليدوي وزيادة قابلية التوسّع بشكل عام. ومع ذلك، يمكنك إنشاء قواعد الملفات الشخصية وقياسها يدويًا في تطبيقك.

تحديد قواعد الملف الشخصي يدويًا

يمكنك تحديد قواعد الملف الشخصي يدويًا في تطبيق أو وحدة مكتبة من خلال إنشاء ملف باسم baseline-prof.txt يقع في الدليل src/main. وهو المجلد نفسه الذي يحتوي على الملف AndroidManifest.xml.

يحدّد الملف قاعدة واحدة لكل سطر. يمثّل كل قاعدة نمطًا لمطابقة الطرق أو الفئات في التطبيق أو المكتبة التي يجب تحسينها.

إنّ بنية هذه القواعد هي مجموعة فرعية من تنسيق ملف تعريف ART القابل للقراءة (HRF) عند استخدام adb shell profman --dump-classes-and-methods. تشبه البنية بنية الواصفات والتواقيع، ولكنها تتيح استخدام أحرف البدل لتبسيط عملية كتابة القواعد.

يعرض المثال التالي بعض قواعد "ملف تعريف الأداء الأساسي" المضمّنة في مكتبة Jetpack Compose:

HSPLandroidx/compose/runtime/ComposerImpl;->updateValue(Ljava/lang/Object;)V
HSPLandroidx/compose/runtime/ComposerImpl;->updatedNodeCount(I)I
HLandroidx/compose/runtime/ComposerImpl;->validateNodeExpected()V
PLandroidx/compose/runtime/CompositionImpl;->applyChanges()V
HLandroidx/compose/runtime/ComposerKt;->findLocation(Ljava/util/List;I)I
Landroidx/compose/runtime/ComposerImpl;

يمكنك محاولة تعديل قواعد الملف الشخصي في نموذج مشروع Compiler Explorer هذا. يُرجى العِلم أنّ أداة Compiler Explorer لا تتوافق إلا مع تنسيق ملف ART القابل للقراءة (HRF)، لذا لا تتوافق مع أحرف البدل.

بنية القاعدة

تتّخذ هذه القواعد أحد الشكلَين التاليَين لاستهداف الطرق أو الفئات:

[FLAGS][CLASS_DESCRIPTOR]->[METHOD_SIGNATURE]

تستخدم قاعدة الفئة النمط التالي:

[CLASS_DESCRIPTOR]

اطّلِع على الجدول التالي للحصول على وصف تفصيلي:

بناء الجملة الوصف
FLAGS تمثّل هذه السمة واحدًا أو أكثر من الأحرف H وS وP للإشارة إلى ما إذا كان يجب وضع علامة Hot أو Startup أو Post Startup على هذه الطريقة فيما يتعلق بنوع بدء التشغيل.

تشير الطريقة التي تحمل العلامة H إلى أنّها طريقة "نشطة"، أي يتم استدعاؤها عدة مرات خلال مدة تشغيل التطبيق.

تشير الطريقة التي تحمل العلامة S إلى أنّها طريقة يتم استدعاؤها أثناء بدء التشغيل.

تشير الطريقة التي تحمل العلامة P إلى أنّها طريقة يتم استدعاؤها بعد بدء التشغيل.

يشير وجود فئة في هذا الملف إلى أنّه يتم استخدامها أثناء بدء التشغيل ويجب تخصيصها مسبقًا في الذاكرة المؤقتة لتجنُّب تكلفة تحميل الفئة. يستخدم برنامج ART المجمّع استراتيجيات تحسين متنوعة، مثل تجميع هذه الطرق مسبقًا (AOT) وإجراء عمليات تحسين للتنسيق في ملف AOT الذي تم إنشاؤه.
CLASS_DESCRIPTOR واصف لفئة الطريقة المستهدَفة. على سبيل المثال، androidx.compose.runtime.SlotTable يتضمّن وصفًا Landroidx/compose/runtime/SlotTable;. يتم إضافة الحرف L هنا وفقًا لتنسيق Dalvik Executable (DEX).
METHOD_SIGNATURE توقيع الطريقة، بما في ذلك الاسم وأنواع المَعلمات وأنواع الإرجاع الخاصة بالطريقة على سبيل المثال:

// LayoutNode.kt

fun isPlaced():Boolean {
// ...
}

على LayoutNode يتضمّن التوقيع isPlaced()Z.

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

قد يبدو مثال على قاعدة أحرف البدل على النحو التالي:

HSPLandroidx/compose/ui/layout/**->**(**)**

الأنواع المتوافقة في قواعد Baseline Profile

تتيح قواعد Baseline Profile الأنواع التالية. لمزيد من التفاصيل حول هذه الأنواع، راجِع تنسيق Dalvik Executable (DEX).

حرف النوع الوصف
B بايت بايت موقّع
C char قيمة موضع رمز Unicode مرمّزة في UTF-16
D مزدوج قيمة النقطة العائمة ذات الدقة المزدوجة
F عائم قيمة النقطة العائمة ذات الدقة الفردية
I تدخُّل دفاعي عدد صحيح
J طويلة عدد صحيح طويل
S فيديو قصير عدد صحيح قصير موقّع
V باطل باطل
Z قيمة منطقية صواب أم خطأ
L (اسم الفئة) المرجع مثيل لاسم فئة

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

تستفيد ART من هذا الملف الشخصي عند استخدام حِزمة APK على الأجهزة لتجميع مجموعة فرعية معيّنة من التطبيق مسبقًا في وقت التثبيت على Android 9 (المستوى 28 لواجهة برمجة التطبيقات) أو Android 7 (المستوى 24 لواجهة برمجة التطبيقات) عند استخدام ProfileInstaller.

جمع ملفات Baseline Profile يدويًا

يمكنك إنشاء "ملف تعريف أساسي" يدويًا بدون إعداد مكتبة Macrobenchmark وإنشاء عمليات تشغيل آلي لواجهة المستخدم لرحلات المستخدمين المهمة. على الرغم من أنّنا ننصح باستخدام Macrobenchmarks، قد لا يكون ذلك ممكنًا دائمًا. على سبيل المثال، إذا كنت تستخدم نظام إنشاء غير Gradle، لن تتمكّن من استخدام المكوّن الإضافي Baseline Profile Gradle. في مثل هذه الحالات، يمكنك جمع قواعد Baseline Profile يدويًا. يكون ذلك أسهل بكثير إذا كنت تستخدم جهازًا أو محاكيًا يعمل بالإصدار 34 من واجهة برمجة التطبيقات أو إصدارًا أحدث. على الرغم من أنّه لا يزال من الممكن إجراء ذلك باستخدام مستويات أدنى من واجهة برمجة التطبيقات، إلا أنّه يتطلّب إذن الوصول إلى الجذر، ويجب استخدام محاكي يعمل بصورة AOSP. يمكنك جمع القواعد مباشرةً من خلال اتّباع الخطوات التالية:

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

    إذا كانت حزمة APK تعتمد على مكتبة Profile Installer من Jetpack، فإنّ المكتبة تبدأ عملية إعداد ملف شخصي عند تشغيل حزمة APK لأول مرة. يمكن أن يتداخل ذلك مع عملية إنشاء الملف الشخصي، لذا عليك إيقافه باستخدام الأمر التالي:

    adb shell am broadcast -a androidx.profileinstaller.action.SKIP_FILE WRITE_SKIP_FILE $PACKAGE_NAME/androidx.profileinstaller.ProfileInstallReceiver
  3. أعِد ضبط تجميع التطبيقات وامحُ أي ملفات شخصية.

    المستوى 34 لواجهة برمجة التطبيقات والإصدارات الأحدث

    adb shell cmd package compile -f -m verify $PACKAGE_NAME
    adb shell pm art clear-app-profiles $PACKAGE_NAME

    المستوى 33 لواجهة برمجة التطبيقات والإصدارات الأقدم

    adb root
    adb shell cmd package compile --reset $PACKAGE_NAME

  4. شغِّل التطبيق وانتقِل يدويًا خلال رحلات المستخدمين الأساسية التي تريد جمع بيانات ملف شخصي لها.

  5. انتظِر خمس ثوانٍ على الأقل إلى أن تستقرّ الملفات الشخصية.

  6. نفِّذ إجراء الحفظ وانتظِر حتى يكتمل. إذا كان ملف APK يعتمد على مكتبة Jetpack Profile Installer، استخدِمها لتفريغ الملفات الشخصية:

    adb shell am broadcast -a androidx.profileinstaller.action.SAVE_PROFILE $PACKAGE_NAME/androidx.profileinstaller.ProfileInstallReceiver
    sleep 1 # wait 1 second
    adb shell am force-stop $PACKAGE_NAME
    إذا كنت لا تستخدم أداة Profile Installer، يمكنك تفريغ الملفات الشخصية يدويًا على محاكي باستخدام الأمر التالي:

    adb root
    adb shell killall -s SIGUSR1 $PACKAGE_NAME
    sleep 1 # wait 1 second
    adb shell am force-stop $PACKAGE_NAME

  7. حوِّل الملفات الشخصية الثنائية التي تم إنشاؤها إلى نص:

    المستوى 34 لواجهة برمجة التطبيقات والإصدارات الأحدث

    adb shell pm dump-profiles --dump-classes-and-methods $PACKAGE_NAME

    المستوى 33 لواجهة برمجة التطبيقات والإصدارات الأقدم

    تحديد ما إذا تم إنشاء ملف شخصي مرجعي أو ملف شخصي حالي يتوفّر ملف مرجعي في الموقع التالي:

    /data/misc/profiles/ref/$$PACKAGE_NAME/primary.prof

    يتوفّر ملف شخصي حالي في الموقع التالي:

    /data/misc/profiles/cur/0/$PACKAGE_NAME/primary.prof

    حدِّد موقع حزمة APK:

    adb root
    adb shell pm path $PACKAGE_NAME

    تنفيذ الإحالة الناجحة:

    adb root
    adb shell profman --dump-classes-and-methods --profile-file=$PROFILE_PATH --apk=$APK_PATH > /data/misc/profman/$PACKAGE_NAME-primary.prof.txt

  8. استخدِم adb لاسترداد الملف التجريبي الذي تم تفريغه من الجهاز:

    adb pull /data/misc/profman/$PACKAGE_NAME-primary.prof.txt PATH_TO_APP_MODULE/src/main/

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

قياس تحسينات التطبيق يدويًا

ننصحك بشدة بقياس تحسينات التطبيق من خلال قياس الأداء. ومع ذلك، إذا كنت تريد قياس التحسينات يدويًا، يمكنك البدء من خلال قياس وقت بدء تشغيل التطبيق غير المحسَّن كمرجع.

PACKAGE_NAME=com.example.app
# Force Stop App
adb shell am force-stop $PACKAGE_NAME
# Reset compiled state
adb shell cmd package compile --reset $PACKAGE_NAME
# Measure App startup
# This corresponds to `Time to initial display` metric.
adb shell am start-activity -W -n $PACKAGE_NAME/.ExampleActivity \
 | grep "TotalTime"

بعد ذلك، حمِّل ملف Baseline Profile.

# Unzip the Release APK first.
unzip release.apk
# Create a ZIP archive.
# The name should match the name of the APK.
# Copy `baseline.prof{m}` and rename it `primary.prof{m}`.
cp assets/dexopt/baseline.prof primary.prof
cp assets/dexopt/baseline.profm primary.profm
# Create an archive.
zip -r release.dm primary.prof primary.profm
# Confirm that release.dm only contains the two profile files:
unzip -l release.dm
# Archive:  release.dm
#   Length      Date    Time    Name
# ---------  ---------- -----   ----
#      3885  1980-12-31 17:01   primary.prof
#      1024  1980-12-31 17:01   primary.profm
# ---------                     -------
#                               2 files
# Install APK + Profile together.
adb install-multiple release.apk release.dm

للتحقّق من تحسين الحزمة عند التثبيت، نفِّذ الأمر التالي:

# Check dexopt state.
adb shell dumpsys package dexopt | grep -A 1 $PACKAGE_NAME

يجب أن توضّح المخرجات أنّه تم تجميع الحزمة:

[com.example.app]
  path: /data/app/~~YvNxUxuP2e5xA6EGtM5i9A==/com.example.app-zQ0tkJN8tDrEZXTlrDUSBg==/base.apk
  arm64: [status=speed-profile] [reason=install-dm]

يمكنك الآن قياس أداء بدء تشغيل التطبيق كما كان من قبل ولكن بدون إعادة ضبط الحالة المجمَّعة. تأكَّد من عدم إعادة ضبط الحالة المجمّعة للحزمة.

# Force stop app
adb shell am force-stop $PACKAGE_NAME
# Measure app startup
adb shell am start-activity -W -n $PACKAGE_NAME/.ExampleActivity \
 | grep "TotalTime"

ملفات Baseline Profile وأداة profgen

يوضّح هذا القسم ما تفعله الأداة profgen عند إنشاء نسخة ثنائية مضغوطة من ملف تعريف Baseline.

تساعد أداة Profgen-cli في تجميع الملفات الشخصية وفحصها وتحويلها إلى تنسيق آخر، ما يتيح تثبيتها على أجهزة Android بغض النظر عن إصدار حزمة تطوير البرامج (SDK) المستهدَف.

‫Profgen-cli هي واجهة سطر أوامر تعمل على تجميع ملف HRF الخاص بملف Baseline Profile إلى تنسيقه المجمّع. تتوفّر واجهة سطر الأوامر أيضًا في مستودع cmdline-tools كجزء من حزمة تطوير البرامج (SDK) لنظام التشغيل Android.

تتوفّر هذه الميزات في فرع studio-main:

 ../cmdline-tools/latest/bin
apkanalyzer
avdmanager
lint
profgen
retrace
screenshot2
sdkmanager

إنشاء ملفات تعريف ثنائية مضغوطة باستخدام Profgen-cli

الطلبات المتاحة مع Profgen-cli هي bin وvalidate وdumpProfile. للاطّلاع على الأوامر المتاحة، استخدِم profgen --help:

  profgen --help
Usage: profgen options_list
Subcommands:
    bin - Generate Binary Profile
    validate - Validate Profile
    dumpProfile - Dump a binary profile to a HRF

Options:
    --help, -h -> Usage info

استخدِم الأمر bin لإنشاء ملف تعريف ثنائي مضغوط. في ما يلي مثال على استدعاء:

profgen bin ./baseline-prof.txt \
  --apk ./release.apk \
  --map ./obfuscation-map.txt \
  --profile-format v0_1_0_p \
  --output ./baseline.prof \

للاطّلاع على الخيارات المتاحة، استخدِم profgen bin options_list:

Usage: profgen bin options_list
Arguments:
    profile -> File path to Human Readable profile { String }
Options:
    --apk, -a -> File path to apk (always required) { String }
    --output, -o -> File path to generated binary profile (always required)
    --map, -m -> File path to name obfuscation map { String }
    --output-meta, -om -> File path to generated metadata output { String }
    --profile-format, -pf [V0_1_0_P] -> The ART profile format version
      { Value should be one of [
         v0_1_5_s, v0_1_0_p, v0_0_9_omr1, v0_0_5_o, v0_0_1_n
        ]
      }
    --help, -h -> Usage info

تمثّل الوسيطة الأولى مسار baseline-prof.txt HRF.

يحتاج Profgen-cli أيضًا إلى مسار إصدار APK ومسار خريطة التشويش التي تُستخدم لتشويش حزمة APK عند استخدام R8 أو Proguard. بهذه الطريقة، يمكن profgen ترجمة رموز المصدر في ملف HRF إلى الأسماء المشوّشة المقابلة عند إنشاء الملف الشخصي المجمَّع.

بما أنّ تنسيقات ملفات ART الشخصية غير متوافقة مع الإصدارات الأحدث أو الأقدم، يجب توفير تنسيق ملف شخصي لكي تحزم حزم profgen البيانات الوصفية للملف الشخصي (profm) التي يمكنك استخدامها لتحويل ترميز تنسيق ملف ART شخصي إلى آخر عند الحاجة.

تنسيقات الملفات الشخصية وإصدارات المنصات

تتوفّر الخيارات التالية عند اختيار تنسيق ملف شخصي:

تنسيق الملف الشخصي إصدار النظام الأساسي مستوى واجهة برمجة التطبيقات
v0_1_5_s الإصدارات Android S والإصدارات الأحدث أكثر من 31
v0_1_0_p ‫Android P وQ وR 28-30
v0_0_9_omr1 Android O MR1 27
v0_0_5_o Android O 26
v0_0_1_n Android N 24-25

انسخ ملفَي الإخراج baseline.prof وbaseline.profm إلى المجلد assets أو dexopt في حزمة APK.

خرائط التشويش

ما عليك سوى تقديم خريطة التشويش إذا كان ملف HRF يستخدم رموز المصدر. إذا تم إنشاء ملف HRF من إصدار تم إخفاء تشويشه مسبقًا ولم يكن من الضروري إجراء عملية ربط، يمكنك تجاهل هذا الخيار ونسخ النواتج إلى المجلد assets أو dexopt.

التثبيت التقليدي لـ Baseline Profiles

يتم عادةً إرسال Baseline Profiles إلى الجهاز بإحدى الطريقتَين التاليتَين.

استخدام install-multiple مع DexMetadata

على الأجهزة التي تعمل بالإصدار 28 من واجهة برمجة التطبيقات والإصدارات الأحدث، ينزّل عميل Play حمولة APK وDexMetadata (DM) لإصدار APK يتم تثبيته. يحتوي ملف DM على معلومات الملف الشخصي التي يتم نقلها إلى "مدير الحِزم" على الجهاز.

يتم تثبيت حزمة APK وDM كجزء من جلسة تثبيت واحدة باستخدام ما يلي:

adb install-multiple base.apk base.dm

‫ProfileInstaller في Jetpack

على الأجهزة التي تعمل بالمستوى 29 من واجهة برمجة التطبيقات والإصدارات الأحدث، يوفّر مكتبة Jetpack ProfileInstaller آلية بديلة لتثبيت ملف شخصي مضمّن في assets أو dexopt بعد تثبيت حزمة APK على الجهاز. يتم استدعاء ProfileInstaller من خلال ProfileInstallReceiver أو من خلال التطبيق مباشرةً.

تعيد مكتبة ProfileInstaller ترميز الملف الشخصي استنادًا إلى إصدار حزمة تطوير البرامج (SDK) للجهاز المستهدف، وتنسخ الملف الشخصي إلى الدليل cur على الجهاز (وهو دليل مرحلي خاص بالحزمة لملفات ART الشخصية على الجهاز).

بعد أن يصبح الجهاز غير نشط، يتم بعد ذلك استلام الملف الشخصي من خلال عملية تُعرف باسم bg-dexopt على الجهاز.

تحميل ملف Baseline Profile

يوضّح هذا القسم كيفية تثبيت ملف Baseline Profile باستخدام حزمة APK.

إعلان رسالة باستخدام androidx.profileinstaller

على الأجهزة التي تعمل بالإصدار 24 من واجهة برمجة التطبيقات والإصدارات الأحدث، يمكنك بث أمر لتثبيت الملف الشخصي:

# Broadcast the install profile command - moves binary profile from assets
#     to a location where ART uses it for the next compile.
#     When successful, the following command prints "1":
adb shell am broadcast \
    -a androidx.profileinstaller.action.INSTALL_PROFILE \
    <pkg>/androidx.profileinstaller.ProfileInstallReceiver

# Kill the process
am force-stop <pkg>

# Compile the package based on profile
adb shell cmd package compile -f -m speed-profile <pkg>

لا تتوفّر ProfileInstaller في معظم حِزم APK التي تتضمّن "ملفات تعريف Baseline"، أي في حوالي 77 ألف تطبيق من أصل 450 ألف تطبيق على Play، ولكنّها تتوفّر في كل حِزمة APK تستخدم Compose. ويرجع ذلك إلى أنّ المكتبات يمكنها توفير ملفات شخصية بدون الإشارة إلى أنّها تعتمد على ProfileInstaller. تتم إضافة تبعية في كل مكتبة تتضمّن ملفًا شخصيًا بدءًا من Jetpack.

استخدام install-multiple مع profgen أو DexMetaData

على الأجهزة التي تعمل بالإصدار 28 من واجهة برمجة التطبيقات والإصدارات الأحدث، يمكنك تحميل ملف Baseline Profile من مصدر خارجي بدون الحاجة إلى تضمين مكتبة ProfileInstaller في التطبيق.

لإجراء ذلك، استخدِم Profgen-cli:

profgen extractProfile \
        --apk app-release.apk \
        --output-dex-metadata app-release.dm \
        --profile-format V0_1_5_S # Select based on device and the preceding table.

# Install APK and the profile together
adb install-multiple appname-release.apk appname-release.dm

لإتاحة تقسيم حِزم APK، نفِّذ خطوات استخراج الملف الشخصي السابقة مرة واحدة لكل حِزمة APK. عند التثبيت، مرِّر كل حِزمة APK وملف .dm المرتبط بها، وتأكَّد من تطابق اسمَي حِزمة APK وملف .dm:

adb install-multiple appname-base.apk appname-base.dm \
appname-split1.apk appname-split1.dm

إثبات الملكية

للتحقّق من تثبيت الملف بشكل صحيح، يمكنك اتّباع الخطوات الواردة في مقالة قياس تحسينات التطبيق يدويًا.

تفريغ محتويات ملف تعريف ثنائي

لفحص محتويات إصدار ثنائي مضغوط من ملف Baseline Profile، استخدِم الخيار Profgen-cli dumpProfile:

Usage: profgen dumpProfile options_list
Options:
    --profile, -p -> File path to the binary profile (always required)
    --apk, -a -> File path to apk (always required) { String }
    --map, -m -> File path to name obfuscation map { String }
    --strict, -s [true] -> Strict mode
    --output, -o -> File path for the HRF (always required) { String }
    --help, -h -> Usage info

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

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

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