מומלץ מאוד ליצור כללי פרופיל באופן אוטומטי באמצעות ספריית Macrobenchmark של Jetpack כדי לצמצם את המאמץ הידני ולהגדיל את יכולת ההתאמה לעומס. עם זאת, אפשר ליצור כללי פרופיל באפליקציה ולמדוד אותם באופן ידני.
הגדרת כללי פרופיל באופן ידני
אפשר להגדיר כללי פרופיל באופן ידני באפליקציה או במודול ספרייה על ידי יצירת קובץ בשם 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/**->**(**)**
סוגי הנתונים הנתמכים בכללים של פרופיל Baseline
הכללים של פרופיל הבסיס תומכים בסוגי הנתונים הבאים. פרטים על הסוגים האלה מופיעים במאמר פורמט Dalvik Executable (DEX).
תו | סוג | תיאור |
---|---|---|
B |
בייט | בייט חתום |
C |
char | נקודת קוד של תו Unicode בקידוד UTF-16 |
D |
כפול | ערך נקודה צפה בדיוק כפול |
F |
float | ערך נקודה צפה ברמת דיוק יחידה |
I |
INT | מספר שלם |
J |
ארוך | מספר שלם ארוך |
S |
סרטון קצר | סרטון Shorts חתום |
V |
ריק | ביטול |
Z |
בוליאני | נכון או לא נכון |
L (שם הכיתה) |
reference | מופע של שם מחלקה |
בנוסף, ספריות יכולות להגדיר כללים הארוזים בפריטי מידע שנוצרו בתהליך פיתוח (Artifact) של AAR. כשמפתחים קובץ APK שכולל את הפריטים האלה, הכללים ממוזגים יחד – בדומה לאופן שבו מתבצע המיזוג של המניפסט – ומקובצים לפרופיל ART בינארי קומפקטי שספציפי לקובץ ה-APK.
כשמשתמשים ב-APK במכשירים, הפרופיל הזה מאפשר ל-ART לבצע הידור AOT של קבוצת משנה ספציפית של האפליקציה בזמן ההתקנה ב-Android 9 (רמת API 28) או ב-Android 7 (רמת API 24) כשמשתמשים ב-ProfileInstaller
.
איסוף ידני של פרופילים Baseline
אפשר ליצור פרופיל בסיס באופן ידני בלי להגדיר את ספריית Macrobenchmark, וליצור אוטומציות של ממשק המשתמש בתהליכי השימוש הקריטיים. למרות שאנחנו ממליצים להשתמש במדדי מאקרובנצ'מרק, יכול להיות שלא תמיד זה יהיה אפשרי. לדוגמה, אם אתם משתמשים במערכת build שאינה של Gradle, לא תוכלו להשתמש בפלאגין Baseline Profile Gradle. במקרים כאלה, אפשר לאסוף באופן ידני כללים של פרופיל הבסיס. קל יותר לעשות זאת אם משתמשים במכשיר או במהדר שפועלים עם API 34 ואילך. אפשר לעשות זאת גם ברמות API נמוכות יותר, אבל צריך הרשאת root ולהשתמש במהדר (emulator) שפועל עם קובץ אימג' של AOSP. כדי לאסוף כללים ישירות:
- מתקינים גרסה זמינה של האפליקציה במכשיר לבדיקה. כדי לקבל פרופיל מדויק, סוג ה-build של האפליקציה צריך להיות מותאם ל-R8 ולא ניתן לניפוי באגים.
- חשוב לוודא שהפרופילים עדיין לא עברו הידור.
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 יש תלות בספרייה Profile Installer של Jetpack, הספרייה תיצור פרופיל בזמן ההפעלה הראשונה של ה-APK. הפעולה הזו עלולה להפריע לתהליך יצירת הפרופיל, לכן צריך להשבית אותה באמצעות הפקודה הבאה:
adb shell am broadcast -a androidx.profileinstaller.action.SKIP_FILE $PACKAGE_NAME/androidx.profileinstaller.ProfileInstallReceiver
- מריצים את האפליקציה ומנווטים באופן ידני במסלולי חוויית המשתמש החיוניים שרוצים לאסוף עבורם פרופיל.
- מבקשים מ-ART לפמפם את הפרופילים. אם ה-APK תלוי בספרייה של מנהל ההתקנה של פרופיל Jetpack, צריך להשתמש בה כדי להציב את הפרופילים:
אם לא משתמשים בכלי ההתקנה של הפרופילים, מוסיפים את הפרופילים באופן ידני לאמולטור באמצעות הפקודה הבאה:adb shell am broadcast -a androidx.profileinstaller.action.SAVE_FILE $PACKAGE_NAME/androidx.profileinstaller.ProfileInstallReceiver adb shell am force-stop $PACKAGE_NAME
adb root adb shell killall -s SIGUSR1 $PACKAGE_NAME 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/
הפעולה הזו מאחזרת את כללי הפרופיל שנוצרו ומתקינה אותם במודול האפליקציה. בפעם הבאה שתיצרו את האפליקציה, פרופיל הבקרה יהיה כלול בה. כדי לוודא זאת, פועלים לפי השלבים בקטע בעיות בהתקנה.
מדידה ידנית של שיפורים באפליקציה
מומלץ מאוד למדוד את השיפורים באפליקציות באמצעות נקודות השוואה. עם זאת, אם אתם רוצים למדוד את השיפורים באופן ידני, תוכלו להתחיל למדוד את הפעלת האפליקציה ללא אופטימיזציה לצורך השוואה.
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"
פרופילים ופרוגן בסיסיים
בקטע הזה מוסבר מה הכלי profgen עושה כשמפתחים גרסה בינארית קומפקטית של פרופיל בסיס.
בעזרת Profgen-cli אתם יכולים לבצע הידור של פרופילים, בדיקה עצמית והחלפת פרופילי ART, כדי שיהיה אפשר להתקין אותם במכשירים מבוססי Android בלי קשר לגרסת היעד של ה-SDK.
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
.
בנוסף, צריך לציין את הנתיב ל-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.
מפות ערפול
צריך לספק את מפת הטשטוש רק אם ב-HRF נעשה שימוש בסמלי מקור. אם HRF נוצר מגרסת build של גרסה שכבר מעורפלת (obfuscated) ולא נדרש מיפוי, אפשר להתעלם מהאפשרות הזו ולהעתיק את הפלט לתיקייה assets
או dexopt
.
התקנה רגילה של פרופילי 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 במכשיר. ProfileInstallReceiver
או האפליקציה עצמה מפעילים את ProfileInstaller
.
הספרייה ProfileInstaller מבצעת המרה של הפרופיל על סמך גרסת ה-SDK של מכשיר היעד, ומעתיקה את הפרופיל לספרייה cur
במכשיר (ספריית טרום-פריסה ספציפית לחבילה לפרופילים של ART במכשיר).
כשהמכשיר לא פעיל, הפרופיל נאסף על ידי תהליך שנקרא bg-dexopt
במכשיר.
טעינת פרופיל 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 עם פרופילים בסיסיים – שנמצאים בכ-77,000 מתוך 450,000 האפליקציות ב-Play – אבל הוא נמצא כמעט בכל חבילת APK שמשתמשת ב-Compose. הסיבה לכך היא שספריות יכולות לספק פרופילים בלי להצהיר על תלות ב-ProfileInstaller. הוספת יחסי תלות בכל ספרייה עם פרופיל חלה החל מ-Jetpack.
שימוש ב-install-multiple
עם פרוגן או 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
ל-dumpProfile
דרושה ה-APK כי הייצוג הבינארי הקומפקטי מאחסן רק היסט DEX, ולכן הוא זקוק להם כדי לשחזר שמות של מחלקות ושיטות.
מצב קפדני מופעל כברירת מחדל, והוא מבצע בדיקת תאימות של הפרופיל לקובצי ה-DEX ב-APK. אם אתם מנסים לנפות באגים בפרופילים שנוצרו באמצעות כלי אחר, יכול להיות שתקבלו שגיאות תאימות שמונעות מכם ליצור גרסת dump לצורך בדיקה. במקרים כאלה, אפשר להשבית את המצב המחמיר באמצעות --strict false
. עם זאת, ברוב המקרים כדאי להשאיר את המצב הקפדני מופעל.
מפת ערפול היא אופציונלית. אם היא מסופקת, היא עוזרת למפות מחדש סמלים שעברו ערפול לגרסאות שקריאות לבני אדם, כדי להקל על השימוש.
מומלץ עבורך
- הערה: טקסט הקישור מוצג כאשר JavaScript מושבת
- שיטות מומלצות לשיפור הביצועים של SQLite
- פרופילים בסיסיים {:#baseline-profiles}
- wake locks חלקיים ממושכים