מומלץ מאוד להפוך את היצירה של כללי הפרופיל לאוטומטית באמצעות ספריית Jetpack Macrobenchmark כדי לצמצם את המאמץ הידני ולהגדיל את יכולת ההתאמה הכללית לעומס. עם זאת, אפשר ליצור ולמדוד כללי פרופיל באפליקציה באופן ידני.
הגדרה ידנית של כללי פרופיל
אפשר להגדיר כללי פרופיל באופן ידני באפליקציה או במודול ספרייה על ידי יצירת קובץ בשם baseline-prof.txt שנמצא בספרייה src/main. זו אותה תיקייה שמכילה את הקובץ AndroidManifest.xml.
הקובץ מציין כלל אחד בכל שורה. כל כלל מייצג תבנית להתאמת שיטות או מחלקות באפליקציה או בספרייה שצריך לבצע להן אופטימיזציה.
התחביר של הכללים האלה הוא קבוצת-על של פורמט הפרופיל של ART שקריא לאנשים (HRF) כשמשתמשים ב-adb shell profman --dump-classes-and-methods. התחביר דומה לתחביר של מתארים וחתימות, אבל מאפשר להשתמש בתווים כלליים לחיפוש כדי לפשט את תהליך כתיבת הכללים.
בדוגמה הבאה מוצגים כמה כללים של פרופיל Baseline שכלולים בספריית 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 ביחס לסוג ההפעלה. method עם הדגל H מציין שזהו method "חם", כלומר הוא נקרא פעמים רבות במהלך חיי האפליקציה. method עם הדגל S מציין שזהו method שנקרא במהלך ההפעלה. מתודה עם הדגל 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/**->**(**)**
סוגים נתמכים בכללים של פרופיל Baseline
כללי Baseline Profile תומכים בסוגים הבאים. לפרטים על הסוגים האלה, עיינו במאמר בנושא הפורמט של Dalvik Executable (DEX).
| דמות | סוג | תיאור |
|---|---|---|
B |
בייט | בייט חתום |
C |
char | מיקום תו (code point) של Unicode בקידוד UTF-16 |
D |
דאבל | ערך נקודה צפה (floating point) עם דיוק כפול |
F |
float | ערך של נקודה צפה (floating-point) עם דיוק יחיד |
I |
INT | מספר שלם |
J |
ארוך | מספר שלם ארוך |
S |
סרטון קצר | סרטון Shorts בשפת הסימנים |
V |
void | ביטול |
Z |
בוליאני | נכון או לא נכון? |
L (שם הכיתה) |
אזכור : התייחסות : הפניה [לפי ההקשר] | מופע של שם מחלקה |
בנוסף, ספריות יכולות להגדיר כללים שנארזים בקובצי AAR. כשיוצרים קובץ APK שכולל את פריטי המידע האלה, הכללים מתמזגים יחד – בדומה למיזוג מניפסט – ומקומפלים לפרופיל ART בינארי קומפקטי שספציפי לקובץ ה-APK.
ART משתמש בפרופיל הזה כשה-APK נמצא בשימוש במכשירים כדי לבצע הידור AOT של קבוצת משנה ספציפית של האפליקציה בזמן ההתקנה ב-Android 9 (רמת API 28), או ב-Android 7 (רמת API 24) כשמשתמשים ב-ProfileInstaller.
איסוף ידני של פרופילי Baseline
אתם יכולים ליצור פרופיל Baseline באופן ידני בלי להגדיר את ספריית Macrobenchmark, וליצור אוטומציות של ממשק המשתמש של חוויות השימוש ההכרחיות (CUJ). למרות שאנחנו ממליצים להשתמש ב-Macrobenchmark, לא תמיד זה אפשרי. לדוגמה, אם אתם משתמשים במערכת build שאינה של Gradle, אתם לא יכולים להשתמש בפלאגין Baseline Profile Gradle. במקרים כאלה, אתם יכולים לאסוף באופן ידני את הכללים של פרופיל Baseline. הרבה יותר קל לעשות את זה אם משתמשים במכשיר או באמולטור עם API מגרסה 34 ומעלה. אפשר לעשות את זה גם ברמות API נמוכות יותר, אבל צריך גישת root ולהשתמש באמולטור שמריץ קובץ אימג' של AOSP. כדי לאסוף כללים ישירות:
- מתקינים גרסת הפצה של האפליקציה במכשיר בדיקה. כדי לתעד פרופיל שבו מערכת build יכולה להשתמש, סוג build של האפליקציה לא יכול להיות מותאם ל-R8 ולא יכול להיות ניתן לבצע ניפוי באגים.
- השבתת ההתקנה של הפרופיל וסגירת האפליקציה.
אם ה-APK שלכם תלוי בספריית Profile Installer של Jetpack, הספרייה תפעיל פרופיל בהפעלה הראשונה של ה-APK. זה יכול להפריע לתהליך יצירת הפרופיל, אז צריך להשבית אותו באמצעות הפקודה הבאה:
adb shell am broadcast -a androidx.profileinstaller.action.SKIP_FILE WRITE_SKIP_FILE $PACKAGE_NAME/androidx.profileinstaller.ProfileInstallReceiver
איפוס של הידור האפליקציה ומחיקת כל הפרופילים.
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
מפעילים את האפליקציה ומנווטים באופן ידני בחוויית שימוש הכרחית (CUJ) שרוצים לאסוף בשבילם פרופיל.
ממתינים לפחות חמש שניות כדי לאפשר לפרופילים להתייצב.
מבצעים את פעולת השמירה וממתינים עד שהיא תסתיים. אם חבילת ה-APK תלויה בספריית Jetpack Profile Installer, צריך להשתמש בה כדי להעביר את הפרופילים:
אם אתם לא משתמשים ב-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
adb root adb shell killall -s SIGUSR1 $PACKAGE_NAME sleep 1 # wait 1 second adb shell am force-stop $PACKAGE_NAME
ממירים את הפרופילים הבינאריים שנוצרו לטקסט:
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
משתמשים ב-
adbכדי לאחזר את הפרופיל שנשמר מהמכשיר:adb pull /data/misc/profman/$PACKAGE_NAME-primary.prof.txt PATH_TO_APP_MODULE/src/main/
הפעולה הזו שולפת את כללי הפרופיל שנוצרו ומתקינה אותם במודול של האפליקציה. בפעם הבאה שתיצרו את האפליקציה, פרופיל ה-Baseline ייכלל בה. כדי לוודא שההתקנה בוצעה כמו שצריך, פועלים לפי השלבים שמפורטים בקטע בעיות בהתקנה.
מדידה ידנית של שיפורים באפליקציה
מומלץ מאוד למדוד את השיפורים באפליקציה באמצעות השוואה לשוק. עם זאת, אם אתם רוצים למדוד את השיפורים באופן ידני, אתם יכולים להתחיל במדידת הפעלת האפליקציה ללא אופטימיזציה, כדי שתהיה לכם נקודת ייחוס.
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 ממקור חיצוני.
# 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 ו-profgen
בקטע הזה מתואר מה הכלי profgen עושה כשיוצרים גרסה בינארית קומפקטית של פרופיל Baseline.
Profgen-cli עוזר לקמפל, לבחון ולבצע טרנספילציה של פרופילי ART, כדי שאפשר יהיה להתקין אותם במכשירים מבוססי Android בלי קשר לגרסת ה-SDK המטורגטת.
Profgen-cli הוא ממשק שורת פקודה (CLI) שמקמפל את ה-HRF של פרופיל Baseline לפורמט המקומפל שלו. ה-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 את הנתיב לגרסת ה-build להפצה של ה-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.
מפות ערפול קוד (obfuscation)
צריך לספק את מפת הערפול רק אם ה-HRF משתמש בסמלי מקור. אם קובץ ה-HRF נוצר מגרסת build להפצה שכבר עברה ערפול ואין צורך במיפוי, אפשר להתעלם מהאפשרות הזו ולהעתיק את הפלט לתיקייה assets או dexopt.
התקנה רגילה של פרופילי Baseline
באופן מסורתי, פרופילים של Baseline מועברים למכשיר באחת משתי דרכים.
שימוש ב-install-multiple עם DexMetadata
במכשירים עם API 28 ואילך, לקוח Play מוריד את ה-APK ואת המטען הייעודי (payload) של 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 במכשיר (ספריית Staging ספציפית לחבילה של פרופילי ART במכשיר).
כשהמכשיר לא פעיל, הפרופיל נאסף על ידי תהליך שנקרא bg-dexopt במכשיר.
איך טוענים פרופיל Baseline ממקורות לא מוכרים (sideload)
בקטע הזה מוסבר איך להתקין פרופיל Baseline באמצעות קובץ 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 עם פרופילים של Baseline – שנמצאים בכ-77,000 מתוך 450,000 אפליקציות ב-Play – אבל הוא נמצא בפועל בכל חבילת APK שמשתמשת ב-Compose. הסיבה לכך היא שספריות יכולות לספק פרופילים בלי להצהיר על תלות ב-ProfileInstaller. הוספת תלות בכל ספרייה עם פרופיל חלה החל מ-Jetpack.
שימוש ב-install-multiple עם profgen או DexMetaData
במכשירים עם API 28 ואילך, אפשר להעביר פרופיל Baseline בלי ספריית 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, משתמשים באפשרות 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
ה-APK נדרש ל-dumpProfile כי הייצוג הבינארי הקומפקטי מאחסן רק היסטים של DEX, ולכן הוא צריך אותם כדי לשחזר שמות של מחלקות ושיטות.
מצב קפדני מופעל כברירת מחדל, והוא מבצע בדיקת תאימות של הפרופיל לקובצי DEX ב-APK. אם אתם מנסים לנפות באגים בפרופילים שנוצרו על ידי כלי אחר, יכול להיות שתקבלו שגיאות תאימות שימנעו מכם לבצע dump לצורך חקירה. במקרים כאלה, אפשר להשבית את המצב הקפדני באמצעות --strict false. עם זאת, ברוב המקרים כדאי להשאיר את המצב הקפדני מופעל.
מפת ערפול היא אופציונלית. אם מספקים אותה, היא עוזרת למפות מחדש סמלים מעורפלים לגרסאות קריאות לאנשים, כדי שיהיה קל יותר להשתמש בהם.
מומלץ בשבילך
- הערה: טקסט הקישור מוצג כש-JavaScript מושבת
- שיטות מומלצות לביצועים של SQLite
- פרופילים של Baseline {:#baseline-profiles}
- חסימות חלקיות ממושכות של מצב השינה