ایجاد و اندازه‌گیری دستی «نمایه‌های مبنا»

اکیداً توصیه می‌کنیم برای کاهش تلاش دستی و افزایش مقیاس‌پذیری عمومی، تولید قوانین نمایه را بااستفاده از کتابخانه Jetpack Macrobenchmark خودکار کنید. بااین‌حال، امکان ایجاد و اندازه‌گیری دستی قوانین نمایه در برنامه‌تان وجود دارد.

تعریف دستی قوانین نمایه

می‌توانید با ایجاد فایلی به‌نام baseline-prof.txt در دایرکتوری src/main، قوانین نمایه را به‌صورت دستی در یک برنامه یا ماژول کتابخانه تعریف کنید. این همان پوشه‌ای است که حاوی فایل AndroidManifest.xml است.

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

نحو این قوانین هنگام استفاده از adb shell profman --dump-classes-and-methods، یک اَبَرمجموعه از قالب نمایه ART قابل‌خواندن برای انسان (HRF) است. نحو شبیه به نحو برای توصیف‌کننده‌ها و امضاها است، اما اجازه می‌دهد از نویسه‌های عام برای ساده کردن فرایند نوشتن قانون استفاده شود.

مثال زیر چند قانون Baseline Profile را نشان می‌دهد که در کتابخانه 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»، به افزونه نمایه‌های خط پایه Android مراجعه کنید.

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

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

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

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

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

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

وقتی از APK در دستگاه‌ها استفاده می‌شود، ART از این نمایه برای کامپایل کردن AOT زیرمجموعه خاصی از برنامه در زمان نصب در Android نسخه ۹ (سطح API‏ ۲۸) یا Android نسخه ۷ (سطح API‏ ۲۴) هنگام استفاده از ProfileInstaller استفاده می‌کند.

جمع‌آوری دستی Baseline Profiles

می‌توانید بدون راه‌اندازی کتابخانه Macrobenchmark، به‌طور دستی «نمایه پایه» تولید کنید و خودکارسازی‌های میانای کاربر را برای مسیرهای قطعی کاربر ایجاد کنید. اگرچه استفاده از Macrobenchmarks را توصیه می‌کنیم، اما ممکن است همیشه امکان‌پذیر نباشد. برای مثال، اگر از سیستم ساخت غیرGradle استفاده می‌کنید، نمی‌توانید از افزونه Gradle «نمایه پایه» استفاده کنید. در این موارد، می‌توانید قوانین Baseline Profile را به‌صورت دستی جمع‌آوری کنید. اگر از دستگاه یا شبیه‌ساز دارای میانای برنامه‌سازی کاربردی ۳۴ و بالاتر استفاده کنید، این کار بسیار آسان‌تر است. اگرچه این کار هنوز با سطوح پایین‌تر API امکان‌پذیر است، اما به دسترسی ریشه نیاز دارد و باید از شبیه‌سازی استفاده کنید که تصویر 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. بازنشانی کردن کامپایل برنامه و پاک کردن همه نمایه‌ها.

    ‫API 34 و بالاتر

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

    میانای برنامه‌سازی کاربردی ۳۳ و پایین‌تر

    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. نمایه‌های دودویی تولیدشده را به نوشتار تبدیل کنید:

    ‫API 34 و بالاتر

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

    میانای برنامه‌سازی کاربردی ۳۳ و پایین‌تر

    تعیین کنید که آیا نمایه مرجع یا نمایه فعلی ایجاد شده است یا نه. نمایه مرجع در مکان زیر قرار دارد:

    /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/

این کار قوانین نمایه تولیدشده را می‌کشد و آن‌ها را در واحد برنامه شما نصب می‌کند. دفعه بعد که برنامه را می‌سازید، Baseline Profile اضافه می‌شود. با دنبال کردن مراحل موجود در مشکلات نصب، این موضوع را تأیید کنید.

سنجش دستی بهبودهای برنامه

اکیداً توصیه می‌کنیم که بهبودهای برنامه را ازطریق محک‌زنی بسنجید. بااین‌حال، اگر می‌خواهید بهبودها را به‌صورت دستی اندازه‌گیری کنید، می‌توانید با اندازه‌گیری راه‌اندازی برنامه بهینه‌سازی‌نشده به‌عنوان مرجع شروع کنید.

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 کمک می‌کند تا بتوان آن‌ها را بدون درنظر گرفتن نسخه کیت توسعه نرم‌افزار هدف در دستگاه‌های مجهز به Android نصب کرد.

‫Profgen-cli یک CLI است که HRF یک «نمایه مبنا» را به قالب کامپایل‌شده آن کامپایل می‌کند. رابط خط فرمان همچنین در مخزن cmdline-tools به‌عنوان بخشی از کیت توسعه نرم‌افزار 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 به قالب دیگر استفاده کنید.

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

هنگام انتخاب قالب نمایه، گزینه‌های زیر دردسترس است:

قالب نمایه نسخه پلت فرم سطح API
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

«نمایه‌های مبنا» معمولاً به یکی از دو روش زیر به دستگاه ارسال می‌شوند.

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

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

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

adb install-multiple base.apk base.dm

Jetpack ProfileInstaller

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

کتابخانه ProfileInstaller نمایه را براساس نسخه کیت توسعه نرم‌افزار دستگاه هدف تراتبدیل می‌کند و نمایه را در دایرکتوری cur در دستگاه (یک دایرکتوری آماده‌سازی مختص بسته برای نمایه‌های ART در دستگاه) کپی می‌کند.

وقتی دستگاه غیرفعال است، نمایه توسط فرایندی به‌نام bg-dexopt در دستگاه انتخاب می‌شود.

بارگذاری جانبی «نمایه مبنا»

این بخش نحوه نصب Baseline Profile را با داشتن 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های دارای «نمایه‌های پایه» وجود ندارد—که در حدود ۷۷ هزار از ۴۵۰ هزار برنامه در Play وجود دارد—هرچند در عمل در هر APK که از Compose استفاده می‌کند وجود دارد. دلیلش این است که کتابخانه‌ها می‌توانند بدون اعلام وابستگی به ProfileInstaller، نمایه ارائه دهند. افزودن وابستگی در هر کتابخانه با نمایه از Jetpack شروع می‌شود.

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

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

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