پروفایل های پایه را به صورت دستی ایجاد و اندازه گیری کنید

برای کاهش تلاش دستی و افزایش مقیاس پذیری عمومی، ما به شدت توصیه می کنیم که قوانین پروفایل را به صورت خودکار با استفاده از کتابخانه 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، به افزونه Android Baseline Profiles مراجعه کنید.

یک مثال از یک قانون عام ممکن است چیزی شبیه به این باشد:

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

انواع پشتیبانی شده در قوانین نمایه پایه

قوانین نمایه پایه از انواع زیر پشتیبانی می کنند. برای جزئیات بیشتر در مورد این انواع، به فرمت Dalvik Executable (DEX) مراجعه کنید.

شخصیت تایپ کنید توضیحات
B بایت بایت امضا شده
C کاراکتر نقطه کد کاراکتر یونیکد کدگذاری شده در UTF-16
D دو برابر کردن مقدار ممیز شناور با دقت دو برابر
F شناور مقدار ممیز شناور تک دقیق
I بین المللی عدد صحیح
J طولانی عدد صحیح بلند
S کوتاه امضا کوتاه
V باطل باطل
Z بولی درست یا غلط
L (نام کلاس) مرجع نمونه ای از نام کلاس

علاوه بر این، کتابخانه ها می توانند قوانینی را تعریف کنند که در آرتیفکت های AAR بسته بندی شده اند. وقتی یک APK برای گنجاندن این مصنوعات می‌سازید، قوانین با هم ادغام می‌شوند - مشابه نحوه انجام ادغام مانیفست - و در یک نمایه ART باینری فشرده که مخصوص APK است، کامپایل می‌شوند.

وقتی از APK در دستگاه‌ها استفاده می‌شود، ART از این نمایه استفاده می‌کند تا AOT زیرمجموعه خاصی از برنامه را در زمان نصب در Android 9 (سطح API 28) یا Android 7 (سطح API 24) هنگام استفاده از ProfileInstaller کامپایل کند.

پروفایل های پایه را به صورت دستی جمع آوری کنید

می‌توانید بدون راه‌اندازی کتابخانه Macrobenchmark به صورت دستی یک نمایه خط پایه ایجاد کنید و اتوماسیون‌های رابط کاربری سفرهای کاربر مهم خود را ایجاد کنید. اگرچه توصیه می کنیم از Macrobenchmarks استفاده کنید، اما ممکن است همیشه امکان پذیر نباشد. به عنوان مثال، اگر از یک سیستم ساخت غیر Gradle استفاده می کنید، نمی توانید از پلاگین Baseline Profile Gradle استفاده کنید. در چنین مواردی، می توانید قوانین نمایه پایه را به صورت دستی جمع آوری کنید. اگر از دستگاه یا شبیه‌ساز دارای API 34 و بالاتر استفاده می‌کنید، این کار بسیار آسان‌تر است. اگرچه هنوز با سطوح API پایین تر امکان پذیر است، اما نیاز به دسترسی ریشه دارد و شما باید از یک شبیه ساز استفاده کنید که یک تصویر AOSP را اجرا می کند. با انجام موارد زیر می توانید قوانین را مستقیماً جمع آوری کنید:

  1. نسخه انتشاری برنامه خود را روی دستگاه آزمایشی نصب کنید. نوع ساخت اپلیکیشن باید بهینه سازی شده R8 و غیرقابل رفع اشکال برای نمایه دقیق باشد.
  2. مطمئن شوید که نمایه ها از قبل کامپایل نشده اند.

    API 34 و بالاتر

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

    API 33 و پایین تر

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

    اگر APK شما به کتابخانه Jetpack Profile Installer وابستگی دارد، کتابخانه یک نمایه را در اولین راه‌اندازی APK شما راه‌اندازی می‌کند. این می تواند در فرآیند تولید پروفایل تداخل ایجاد کند، بنابراین با دستور زیر آن را غیرفعال کنید:

    adb shell am broadcast -a androidx.profileinstaller.action.SKIP_FILE $PACKAGE_NAME/androidx.profileinstaller.ProfileInstallReceiver
    
  3. برنامه را اجرا کنید و به صورت دستی در میان سفرهای کاربر حیاتی خود که می خواهید برای آنها نمایه جمع آوری کنید پیمایش کنید.
  4. از ART بخواهید که پروفایل ها را تخلیه کند. اگر APK شما به کتابخانه Jetpack Profile Installer وابستگی دارد، از آن برای حذف نمایه ها استفاده کنید:

    adb shell am broadcast -a androidx.profileinstaller.action.SAVE_FILE $PACKAGE_NAME/androidx.profileinstaller.ProfileInstallReceiver
    adb shell am force-stop $PACKAGE_NAME
    
    اگر از Profile Installer استفاده نمی‌کنید، با استفاده از دستور زیر، پروفایل‌ها را به‌صورت دستی در یک شبیه‌ساز تخلیه کنید:

    adb root
    adb shell killall -s SIGUSR1 $PACKAGE_NAME
    adb shell am force-stop $PACKAGE_NAME
    
  5. حداقل پنج ثانیه صبر کنید تا تولید نمایه کامل شود.
  6. پروفایل های باینری تولید شده را به متن تبدیل کنید:

    API 34 و بالاتر

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

    API 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
    

  7. از 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"

در مرحله بعد، نمایه خط پایه را بارگذاری کنید.

# 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"

پروفایل های پایه و profgen

این بخش توضیح می‌دهد که ابزار profgen هنگام ساختن یک نسخه باینری فشرده از یک نمایه خط پایه چه کاری انجام می‌دهد.

Profgen-cli به جمع‌آوری نمایه، درون‌نگری و انتقال نمایه‌های ART کمک می‌کند، بنابراین می‌توان آن‌ها را بدون توجه به نسخه SDK هدف، بر روی دستگاه‌های مجهز به Android نصب کرد.

Profgen-cli یک CLI است که HRF یک نمایه خط پایه را در قالب کامپایل شده آن کامپایل می کند. CLI همچنین در مخزن cmdline-tools به عنوان بخشی از Android SDK ارسال می شود.

این ویژگی ها در شعبه 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

آرگومان اول نشان دهنده مسیر HRF baseline-prof.txt است.

Profgen-cli همچنین به مسیر انتشار APK و یک نقشه مبهم سازی نیاز دارد که برای مبهم کردن APK هنگام استفاده از R8 یا Proguard استفاده می شود. به این ترتیب، profgen می تواند نمادهای منبع در HRF را به نام های مبهم متناظر آنها در هنگام ساختن نمایه کامپایل شده ترجمه کند.

از آنجایی که فرمت‌های نمایه‌های ART سازگار با جلو یا عقب نیستند، یک قالب نمایه ارائه کنید تا profgen متاداده‌های پروفایل ( profm ) را بسته‌بندی کند که در صورت لزوم بتوانید از آن برای تبدیل یک قالب نمایه ART به دیگری در صورت لزوم استفاده کنید.

فرمت های پروفایل و نسخه های پلتفرم

هنگام انتخاب فرمت نمایه گزینه های زیر در دسترس هستند:

فرمت نمایه نسخه پلتفرم سطح API
v0_1_5_s اندروید S+ 31+
v0_1_0_p اندروید پی، کیو و آر 28-30
v0_0_9_omr1 اندروید O MR1 27
v0_0_5_o اندروید O 26
v0_0_1_n اندروید N 24-25

فایل های خروجی baseline.prof و baseline.profm را در پوشه assets یا dexopt در APK کپی کنید.

نقشه های مبهم سازی

اگر HRF از نمادهای منبع استفاده می کند، فقط باید نقشه مبهم سازی را ارائه دهید. اگر HRF از یک نسخه منتشر شده تولید شده است که قبلاً مبهم است و نیازی به نقشه برداری نیست، می توانید آن گزینه را نادیده بگیرید و خروجی ها را در پوشه assets یا dexopt کپی کنید.

نصب سنتی پروفایل های پایه

نمایه های خط پایه به طور سنتی به یکی از دو روش به دستگاه تحویل داده می شوند.

از install-multiple با DexMetadata استفاده کنید

در دستگاه‌های دارای API 28 و بالاتر، کلاینت Play فایل APK و DexMetadata (DM) را برای نسخه APK در حال نصب دانلود می‌کند. DM حاوی اطلاعات نمایه است که در دستگاه به Package Manager ارسال می شود.

APK و DM به عنوان بخشی از یک جلسه نصب با استفاده از موارد زیر نصب می شوند:

adb install-multiple base.apk base.dm

Jetpack ProfileInstaller

در دستگاه‌های دارای API سطح 29 و بالاتر، کتابخانه Jetpack ProfileInstaller مکانیزم جایگزینی برای نصب نمایه بسته‌بندی شده در assets یا dexopt پس از نصب APK در دستگاه ارائه می‌کند. ProfileInstaller توسط ProfileInstallReceiver یا مستقیماً توسط برنامه فراخوانی می شود.

کتابخانه ProfileInstaller نمایه را بر اساس نسخه SDK دستگاه مورد نظر رمزگذاری می‌کند و نمایه را در فهرست cur روی دستگاه کپی می‌کند.

هنگامی که دستگاه بیکار است، نمایه توسط فرآیندی به نام bg-dexopt در دستگاه برداشت می شود.

یک نمایه پایه را بارگیری کنید

این بخش نحوه نصب نمایه خط پایه را با یک APK توضیح می دهد.

پخش با androidx.profileinstaller

در دستگاه‌های دارای API 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 با نمایه‌های پایه - که در حدود 77 هزار برنامه از 450 هزار برنامه در Play وجود دارد - وجود ندارد - اگرچه به طور مؤثر در هر APK با استفاده از Compose وجود دارد. این به این دلیل است که کتابخانه ها می توانند پروفایل ها را بدون اعلام وابستگی به ProfileInstaller ارائه دهند. افزودن یک وابستگی در هر کتابخانه با نمایه با شروع با Jetpack اعمال می شود.

از install-multiple با profgen یا DexMetaData استفاده کنید

در دستگاه‌هایی که API 28 و جدیدتر دارند، می‌توانید یک نمایه پایه را بدون نیاز به کتابخانه 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

تأیید

برای تأیید اینکه نمایه به درستی نصب شده است، می‌توانید از مراحل اندازه‌گیری دستی بهبود برنامه استفاده کنید.

محتویات یک نمایه باینری را تخلیه کنید

برای بررسی درونی محتوای یک نسخه باینری فشرده از یک نمایه پایه، از گزینه 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 غیرفعال کنید. با این حال، در بیشتر موارد باید حالت سخت را فعال نگه دارید.

نقشه مبهم اختیاری است. در صورت ارائه، به بازنگری نمادهای مبهم به نسخه های قابل خواندن توسط انسان برای سهولت استفاده کمک می کند.

{% کلمه به کلمه %} {% آخر کلمه %} {% کلمه به کلمه %} {% آخر کلمه %}