מומלץ מאוד ליצור כללי פרופיל באופן אוטומטי באמצעות ספריית 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 | מיקום תו (code point) של תו Unicode שמקודד ב-UTF-16 |
D |
double | ערך נקודה צפה (floating-point) עם דיוק כפול |
F |
float | ערך נקודה צפה (floating-point) ברמת דיוק יחידה |
I |
INT | מספר שלם |
J |
ארוך | מספר שלם ארוך |
S |
סרטון קצר | סרטון Shorts חתום |
V |
void | ביטול |
Z |
בוליאני | נכון או לא נכון |
L (שם הכיתה) |
reference | מופע של שם כיתה |
בנוסף, בספריות אפשר להגדיר כללים שמארזים בארטיפקטים של 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 שלכם תלויה בספריית Profile Installer של Jetpack, תוכלו להשתמש בה כדי לדגום את הפרופילים:
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
- ממתינים לפחות חמש שניות עד שהיצירה של הפרופיל תושלם.
- ממירים את הפרופילים הבינאריים שנוצרים לטקסט:
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"
פרופילים Baseline ו-profgen
בקטע הזה מוסבר מה הכלי 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 של גרסה שהושחתה כבר, ואין צורך במיפוי, אפשר להתעלם מהאפשרות הזו ולהעתיק את הפלט לתיקייה assets
או dexopt
.
התקנה רגילה של פרופילי Baseline
בדרך כלל, פרופילים בסיסיים מועברים למכשיר באחת משתי דרכים.
שימוש ב-install-multiple
עם DexMetadata
במכשירים עם API מגרסה 28 ואילך, לקוח Play מוריד את עומס העבודה של ה-APK ו-DexMetadata (DM) של גרסת ה-APK שמותקנת. ה-DM מכיל את פרטי הפרופיל שמועברים ל-Package Manager במכשיר.
התקנת ה-APK וה-DM מתבצעת כחלק מסשן התקנה יחיד באמצעות קוד דומה לזה:
adb install-multiple base.apk base.dm
Jetpack ProfileInstaller
במכשירים עם Android מגרסה 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
עם 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
אימות
כדי לוודא שהפרופיל הוטמע בצורה תקינה, אפשר לפעול לפי השלבים המפורטים במאמר מדידת שיפורים באפליקציה באופן ידני.
איך מעבירים את התוכן של פרופיל בינארי
כדי לבדוק את התוכן של גרסה בינארית קומפקטית של פרופיל בסיס, משתמשים באפשרות dumpProfile
של Profgen-cli:
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 חלקיים ממושכים