כדי לספק את חוויית המשתמש הטובה ביותר, מומלץ לבצע אופטימיזציה של האפליקציה כדי שהיא תהיה קטנה ומהירה ככל האפשר. כלי האופטימיזציה של האפליקציה שלנו, שנקרא R8, מייעל את האפליקציה על ידי הסרת קוד ומשאבים שלא נמצאים בשימוש, כתיבה מחדש של קוד כדי לבצע אופטימיזציה של ביצועי זמן הריצה ועוד. למשתמשים שלכם, המשמעות היא:
- זמן הפעלה מהיר יותר
- שימוש מופחת בזיכרון
- שיפורים בביצועי העיבוד והזמן של הריצה
- פחות מקרי ANR
סקירה כללית על אופטימיזציה של R8
R8 משתמש בתהליך רב-שלבי כדי לבצע אופטימיזציה של האפליקציה מבחינת גודל ומהירות. בין הפעולות העיקריות:
כיווץ קוד (שנקרא גם tree shaking): R8 מזהה ומסיר קוד שלא ניתן להגיע אליו מהאפליקציה ומהתלות שלה בספריות. על ידי ניתוח נקודות הכניסה של האפליקציה (כמו
ActivitiesאוServicesשמוגדרות במניפסט), R8 יוצר גרף של קוד עם הפניות ומסיר כל מה שלא נשאר עם הפניות.אופטימיזציות לוגיות: R8 כותב מחדש את הקוד כדי לשפר את יעילות הביצוע ולהפחית את התקורה. בין הטכניקות העיקריות:
הוספת קוד של שיטה: R8 מחליף אתר של קריאה לשיטה בגוף בפועל של השיטה שנקראה. הפעולה הזו מבטלת את התקורה של קריאה לפונקציה ומאפשרת ל-R8 לבצע אופטימיזציות נוספות.
מיזוג כיתות: R8 משלב קבוצות של כיתות וממשקים לכיתה אחת. כך מצמצמים את מספר המחלקות באפליקציה, מפחיתים את העומס על הזיכרון ומשפרים את מהירות ההפעלה.
ערפול קוד (obfuscation) (שידוע גם כהקטנה): כדי להקטין את הגודל של קובץ ה-DEX, R8 מקצר את השמות של מחלקות, שדות ושיטות (לדוגמה,
com.example.MyActivityיכול להפוך ל-a.b.a).
החל מגרסה 8.12.0 של פלאגין של Android Gradle (AGP), R8 גם מבצע אופטימיזציה של משאבים כחלק משלבי האופטימיזציה שלו. מידע נוסף זמין במאמר בנושא כיווץ מקורות המידע בצורה אופטימלית.
הפעלת אופטימיזציה
כדי להפעיל אופטימיזציה של אפליקציה, צריך להשתמש ב-DSL המתאים על סמך גרסת ה-AGP של הפרויקט. מומלץ להפעיל את האופטימיזציה של האפליקציה רק בגרסה הסופית של האפליקציה שאתם בודקים לפני הפרסום – בדרך כלל בגרסת ה-release – כי האופטימיזציות מגדילות את זמן ה-build של הפרויקט ויכולות להקשות על ניפוי הבאגים בגלל האופן שבו הן משנות את הקוד.
בגרסאות AGP 9.3 ואילך
כדי להפעיל אופטימיזציה של אפליקציות ב-AGP 9.3 ואילך:
- מגדירים את
enable = trueבבלוקoptimizationבסקריפט הבנייה ברמת האפליקציה של גרסת הייצור. - מוסיפים את כללי השמירה לקובץ עם הסיומת
.keepבערכת המקורsrc/<variant>/keepRules. לדוגמה,src/main/keepRules/custom-rules.keep.
Kotlin
android {
buildTypes {
release {
optimization {
enable = true // Enables code and resource optimizations.
}
}
}
}
מגניב
android {
buildTypes {
release {
optimization {
enable = true // Enables code and resource optimizations.
}
}
}
}
שפת תצורה מדור קודם ל-AGP בגרסאות שקודמות ל-9.3
כדי להפעיל אופטימיזציה של האפליקציה, מגדירים את isMinifyEnabled = true (לאופטימיזציה של קוד) ואת isShrinkResources = true (לאופטימיזציה של משאבים) בסקריפט ה-build ברמת האפליקציה של ה-build של הגרסה. מומלץ להפעיל תמיד את שתי ההגדרות.
DSL מדור קודם (Kotlin)
android {
buildTypes {
release {
// Enables code optimizations.
isMinifyEnabled = true
// Enables resource shrinking.
isShrinkResources = true
proguardFiles(
// Default file with automatically generated optimization rules.
getDefaultProguardFile("proguard-android-optimize.txt"),
...
)
...
}
}
...
}
DSL מדור קודם (Groovy)
android {
buildTypes {
release {
// Enables code optimizations.
minifyEnabled = true
// Enables resource shrinking.
shrinkResources = true
// Default file with automatically generated optimization rules.
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt')
...
}
}
}
שיפור האופטימיזציה של R8
היתרונות בביצועים של R8 קשורים ישירות לכמות בסיס הקוד שאפשר לבצע בו אופטימיזציה באמצעות R8. כדי להפיק את המרב מ-R8, מומלץ לפעול לפי השיטות המומלצות הבאות:
- הפעלת R8 במצב מלא
- הפעלה של ערפול קוד (obfuscation), אופטימיזציה וכיווץ
- הפעלת כיווץ מקורות מידע וכיווץ מקורות מידע שעבר אופטימיזציה
- משפרים את כללי השמירה כדי לאפשר אופטימיזציה מקסימלית של מחלקות, שדות ושיטות.
כדי לשפר את כללי השמירה, אפשר להשתמש בכלי לניתוח ההגדרות של R8.
כלי הניתוח של הגדרות R8 מאפשר לכם:
- כדי לעקוב אחרי האיכות הכוללת של הגדרות R8 ולשפר אותה, אפשר לעיין במדדים שמופיעים בדוח של כלי הניתוח של הגדרות R8.
- איך מוצאים את כללי השמירה הרחבים ביותר – אלה שמונעים את רוב האופטימיזציה
- ולהבין איזו אופטימיזציה הם מונעים, כדי לשפר אותם.
כלי הניתוח של הגדרות R8 זמין ב-AGP בגרסה 9.3.0-alpha05 או ב-R8 בגרסה 9.3.7-dev. מידע נוסף זמין במאמר בנושא ניתוח הגדרות R8.
אופטימיזציה של כיווץ מקורות המידע כדי ליצור אפליקציות קטנות עוד יותר
בגרסה 8.12.0 של AGP מוצג כיווץ משאבים שעבר אופטימיזציה, שמטרתו לשלב אופטימיזציה של משאבים וקוד כדי ליצור אפליקציות קטנות ומהירות עוד יותר. לפני האופטימיזציה של צמצום המשאבים, Android Asset Packaging Tool (AAPT2) יצר כללי שמירה שטיפלו בצמצום המשאבים בנפרד מהקוד, ולעתים קרובות שמרו קוד או משאבים שלא הייתה אליהם גישה, או שהייתה הפניה הדדית ביניהם.
בכיווץ משאבים שעבר אופטימיזציה, המשאבים נחשבים כחלק מקוד התוכנית, ויוצרים את תרשים ההפניה. אם לא מתבצעת הפניה לאוסף של קוד או משאבים, הוא לא מוגן על ידי כלל שמירה, ואפשר להסיר אותו.
הפעלה של כיווץ מקורות מידע שעבר אופטימיזציה
כדי להפעיל את צינור ה-**אופטימיזציה** החדש ל**כיווץ מקורות המידע** ב-AGP 8.12 או 8.13, מוסיפים את השורות הבאות לקובץ gradle.properties של ה**פרויקט**:
אם אתם משתמשים ב-AGP 9.0.0 או בגרסה חדשה יותר, אתם לא צריכים להגדיר את android.r8.optimizedResourceShrinking=true. כיווץ מקורות מידע שעבר אופטימיזציה מוחל באופן אוטומטי כשמפעילים את isShrinkResources = true בהגדרות של הגרסה.
אימות והגדרה של הגדרות האופטימיזציה של R8
כדי לאפשר ל-R8 להשתמש ביכולות האופטימיזציה המלאות שלו, צריך להסיר את השורה הבאה מקובץ gradle.properties של הפרויקט, אם היא קיימת:
bash android.enableR8.fullMode=false # Remove this line from your codebase.
שימו לב שהפעלת אופטימיזציה של האפליקציה מקשה על הבנת עקבות מחסנית, במיוחד אם R8 משנה את השמות של מחלקות או שיטות. כדי לקבל מעקב אחר מחסנית (stack trace) שתואם לקוד המקור, אפשר לעיין במאמר בנושא שחזור המעקב המקורי אחר המחסנית.
אם R8 מופעל, כדאי גם ליצור פרופילים להפעלה כדי לשפר עוד יותר את ביצועי ההפעלה.
אם הפעלתם אופטימיזציה של אפליקציות והיא גורמת לשגיאות, הנה כמה אסטרטגיות לפתרון הבעיות:
- הוספת כללי שמירה כדי להשאיר חלק מהקוד ללא שינוי.
- יישום הדרגתי של אופטימיזציות.
- צריך לעדכן את הקוד כדי להשתמש בספריות שמתאימות יותר לאופטימיזציה.
אם אתם רוצים לייעל את מהירות ה-build, במאמר הגדרת אופן ההפעלה של R8 מוסבר איך להגדיר את R8 בהתאם לסביבה שלכם.
שינויים בהתנהגות של גרסאות AGP ו-R8
בטבלה הבאה מפורטות התכונות העיקריות שהוצגו בגרסאות שונות של פלאגין של Android Gradle (AGP) ושל R8 compiler.
| גרסת AGP | תכונות חדשות |
|---|---|
| 9.3 |
שפת תצורה פשוטה יותר (DSL): בלוק חדש של `optimization {}` מאפשר להגדיר פחות הגדרות – כיווץ מקורות מידע שעבר אופטימיזציה תמיד מופעל, וכללי השמירה של Android הם ברירת מחדל שניתן לבטל.
`keepRules` קבוצת מקורות: If you use the new DSL, you must place your keep rules in the src/<variant>/keepRules קבוצת מקורות, in files with the suffix .keep. קבוצות המקורות תואמות גם ל-DSL מדור קודם.
כללים לשימוש ב-KMP (Kotlin MultiPlatform): ב-KMP כבר לא צריך להגדיר את publish = true, ויש תמיכה בקובץ המקור src/<variant>/keepRules עם התוסף .keep.
שימו לב: עדיין יש תמיכה ב-DSL מדור קודם. |
| 9.1 |
מחלקות שנארזות מחדש כברירת מחדל: R8 אורז מחדש מחלקות (מעביר אותן לחבילה ללא שם, ברמה העליונה) כדי לדחוס עוד יותר את קובץ ה-DEX, וכך אין צורך לציין את האפשרות -repackageclasses. מידע על אופן הפעולה של האפשרות הזו ועל אופן ההשבתה שלה זמין במאמר בנושא אפשרויות גלובליות.
|
| 9.0 |
כיווץ מקורות מידע שעבר אופטימיזציה: מופעל כברירת מחדל (נשלט באמצעות android.r8.optimizedResourceShrinking). כיווץ מקורות מידע שעבר אופטימיזציה עוזר לשלב כיווץ מקורות מידע עם צינור האופטימיזציה של הקוד, וכך ליצור אפליקציות קטנות ומהירות יותר. הכלי מבצע אופטימיזציה של הקוד ושל הפניות למשאבים בו-זמנית, וכך הוא מזהה משאבים שההפניה אליהם היא מקוד שלא נמצא בשימוש ומסיר אותם. זהו שיפור משמעותי לעומת תהליכי האופטימיזציה הנפרדים הקודמים.האפשרות הזו שימושית במיוחד לאפליקציות שמשתפות משאבים וקוד משמעותיים בין ענפים שונים של גורמי צורה, עם שיפורים שנמדדו של יותר מ-50% בגודל האפליקציה. הקטנת הגודל מאפשרת הורדות קטנות יותר, התקנות מהירות יותר וחוויית משתמש טובה יותר עם הפעלה מהירה יותר, עיבוד משופר ופחות שגיאות ANR. סינון כללים של ספריות: הוסרה התמיכה באפשרויות גלובליות (לדוגמה, -dontobfuscate) בכללי צרכן של ספריות, והאפליקציות יסננו אותן. מידע נוסף זמין במאמר בנושא הוספת אפשרויות גלובליות.בדיקות של ערכים ריקים (null) ב-Kotlin: אופטימיזציה מופעלת כברירת מחדל (נשלטת באמצעות -processkotlinnullchecks). בגרסה הזו בוצעו גם שיפורים משמעותיים במהירות ה-build. מידע נוסף זמין במאמר בנושא הגדרות גלובליות להוספת אופטימיזציה.אופטימיזציה של חבילות ספציפיות: אפשר להשתמש ב- packageScope כדי לבצע אופטימיזציה של חבילות ספציפיות. התמיכה הזו ניסיונית. מידע נוסף זמין במאמר בנושא אופטימיזציה של חבילות שצוינו באמצעות packageScope.אופטימיזציה כברירת מחדל: הפסקנו לתמוך ב- getDefaultProguardFile("proguard-android.txt") כי הוא כולל את -dontoptimize, ומומלץ להימנע ממנו. במקום זאת, צריך להשתמש ב-"proguard-android-optimize.txt". אם אתם צריכים להשבית את האופטימיזציה באפליקציה באופן גלובלי, צריך להוסיף את הדגל באופן ידני לקובץ Proguard.
|
| 8.12 |
אופטימיזציה של כיווץ משאבים: נוספה תמיכה ראשונית (נשלטת באמצעות android.r8.optimizedResourceShrinking). אופטימיזציה של כיווץ משאבים עוזרת לשלב כיווץ משאבים עם צינור האופטימיזציה של הקוד. צריך להפעיל אותה באופן ידני בגרסה הזו של AGP.Logcat retracing: Support for automatic retracing in the Android Studio Logcat window. |
| 8.6 |
שיפורים באיתור מקורות: כולל איתור מקורות לפי שם הקובץ ומספר השורה כברירת מחדל לכל הרמות של minSdk (בעבר נדרשה רמה 26 ומעלה בגרסה 8.2).minSdkעדכון R8 עוזר לוודא שקובצי מעקב אחר ביצוע (stack trace) מגרסאות build מעורפלות קריאים בקלות ובבירור. בגרסה הזו שיפרנו את המיפוי של מספרי השורות וקבצי המקור, כדי שיהיה קל יותר לכלים כמו Logcat ב-Android Studio לאתר באופן אוטומטי את המקור לקריסות בקוד המקור המקורי. |
| 8.0 |
מצב מלא כברירת מחדל: המצב המלא של R8 מספק אופטימיזציה חזקה משמעותית. ההגדרה הזו מופעלת כברירת מחדל. אפשר לבטל את ההצטרפות באמצעות android.enableR8.fullMode=false.
|
| 7.0 |
מצב מלא זמין: הושק כפיצ'ר אופציונלי באמצעות android.enableR8.fullMode=true. במצב מלא, המערכת מבצעת אופטימיזציות חזקות יותר על ידי הנחה של הנחות מחמירות יותר לגבי האופן שבו הקוד משתמש בהשתקפות ובתכונות דינמיות אחרות. השימוש ב-ProGuard מקטין את גודל האפליקציה ומשפר את הביצועים, אבל יכול להיות שיהיה צורך להוסיף כללי שמירה כדי למנוע את הסרת הקוד הנדרש.
|