יצירת פרופילים בסיסיים

יצירת פרופילים באופן אוטומטי לכל גרסה של האפליקציה באמצעות ספריית Macrobenchmark של Jetpack ו-BaselineProfileRule. מומלץ להשתמש בגרסה com.android.tools.build:gradle:8.0.0 ואילך, שמגיעה עם שיפורים בגרסאות build כשמשתמשים בפרופילים בסיסיים.

אלה השלבים הכלליים ליצירת פרופיל בסיס חדש:

  1. מגדירים את המודול Baseline Profile.
  2. מגדירים את בדיקת JUnit שבעזרתה יוצרים פרופילי Baseline.
  3. מוסיפים את חוויית המשתמש החיונית (CUJ) שרוצים לבצע עבורה אופטימיזציה.
  4. יוצרים את פרופיל Baseline.

אחרי שיוצרים את פרופיל הבסיס, בודקים אותו באמצעות מכשיר פיזי כדי למדוד את שיפורי המהירות.

יצירת פרופיל בסיס חדש עם AGP 8.2 ואילך

הדרך הקלה ביותר ליצור פרופיל Baseline חדש היא להשתמש בתבנית המודול של פרופיל Baseline, שזמינה החל מ-Android Studio Iguana ומ-Android Gradle Plugin ‏ (AGP) 8.2.

התבנית של מודול ה-Baseline Profile Generator ב-Android Studio מאפשרת ליצור באופן אוטומטי מודול חדש ליצירה ולביצוע בדיקת ביצועים של פרופילים בסיסיים. הפעלת התבנית יוצרת את רוב ההגדרות האופייניות של ה-build, יצירת פרופיל הבסיס וקוד האימות. התבנית יוצרת קוד ליצירה ולביצוע בדיקת ביצועים של פרופילים בסיסיים למדידת ההפעלה של האפליקציה.

הגדרת המודול 'פרופיל בסיס'

כדי להריץ את התבנית של מודול פרופיל הבסיס:

  1. בוחרים באפשרות File > New > New Module (קובץ > חדש > מודול חדש).
  2. בוחרים את התבנית Baseline Profile Generator בחלונית Templates ומגדירים אותה:
    איור 1. תבנית המודול של הכלי ליצירת פרופילים Baseline.

    השדות בתבנית הם:

    • אפליקציית היעד: מגדירה לאיזו אפליקציה ייוצר פרופיל הבסיס. אם יש לכם רק מודול אפליקציה אחד בפרויקט, יופיע רק פריט אחד ברשימה הזו.
    • שם המודול: השם שרוצים למודול של פרופיל הבסיס שנוצר.
    • Package name: שם החבילה הרצוי למודול Baseline Profile.
    • Language: האם הקוד שנוצר יהיה ב-Kotlin או ב-Java.
    • שפת הגדרת ה-build: בוחרים אם להשתמש ב-Kotlin Script‏ (KTS) או ב-Groovy בסקריפטים של הגדרת ה-build.
    • שימוש במכשיר בניהול Gradle: האם אתם משתמשים במכשירים בניהול Gradle כדי לבדוק את האפליקציה.
  3. לוחצים על סיום והמודול החדש נוצר. אם אתם משתמשים במערכת בקרת גרסאות, יכול להיות שתתבקשו להוסיף את קובצי המודולים שנוצרו למערכת בקרת הגרסאות.

הגדרת המחולל של פרופיל Baseline

המודול החדש שנוצר מכיל בדיקות ליצירה ולביצוע בדיקת ביצועים של פרופיל הבסיס, וגם לבדיקה של הפעלת האפליקציה הבסיסית בלבד. מומלץ להוסיף להם מסמכי CUJ ותהליכי עבודה מתקדמים לסטארט-אפים. חשוב לוודא שכל הבדיקות שקשורות להפעלה של האפליקציה נמצאות בבלוק rule עם הערך includeInStartupProfile שמוגדר כ-true. לעומת זאת, כדי לשפר את הביצועים, חשוב לוודא שכל הבדיקות שלא קשורות להפעלה של האפליקציה לא נכללות בפרופיל הפעלה. אופטימיזציות של הפעלת האפליקציה משמשות להגדרת חלק מיוחד בפרופיל הבסיס שנקרא פרופיל הפעלה.

כדי לשפר את יכולת התחזוקה, מומלץ ליצור אבסוקציה של ה-CUJs האלה מחוץ לפרופיל הבסיס ולקוד של מדד הביצועים שנוצרו, כדי שניתן יהיה להשתמש בהם בשניהם. המשמעות היא שאפשר להשתמש בשינויים ב-CUJ באופן עקבי.

יצירת פרופיל Baseline והתקנתו

התבנית של מודול פרופיל Baseline מוסיפה הגדרת הפעלה חדשה ליצירת פרופיל Baseline. אם אתם משתמשים ב-flavors של מוצרים, Android Studio יוצר כמה הגדרות הפעלה כדי שתוכלו ליצור פרופילים בסיסיים נפרדים לכל flavor.

הגדרת ההרצה של Generate Baseline Profile.
איור 2. הפעלת ההגדרה הזו יוצרת את פרופיל הבסיס.

בסיום ההגדרה של ההרצה של Generate Baseline Profile, המערכת מעתיקה את פרופיל הבסיס שנוצר לקובץ src/variant/generated/baselineProfiles/baseline-prof.txt שבמודול שרוצים ליצור לו פרופיל. אפשרויות הווריאנט הן סוג ה-build של הגרסה המשוחררת או וריאנט build שכולל את סוג ה-build של הגרסה המשוחררת.

פרופיל Baseline שנוצר נוצר במקור ב-build/outputs. הנתיב המלא נקבע לפי הווריאנט או המאפיינים של האפליקציה שנוצר לה פרופיל, ובהתאם לשימוש במכשיר מנוהל על ידי Gradle או במכשיר מחובר לצורך יצירת הפרופיל. אם משתמשים בשמות שבהם נעשה שימוש בקוד ובהגדרות ה-build שנוצרו על ידי התבנית, פרופיל הבסיס נוצר בקובץ build/outputs/managed_device_android_test_additional_output/nonminifiedrelease/pixel6Api31/BaselineProfileGenerator_generate-baseline-prof.txt. סביר להניח שלא תצטרכו לבצע פעולות ישירות בגרסה הזו של פרופיל הבסיס שנוצר, אלא אם תעתיקו אותו באופן ידני למודול היעד (לא מומלץ).

יצירת פרופיל בסיס חדש באמצעות AGP 8.1

אם אתם לא יכולים להשתמש בתבנית המודול של Baseline Profile, תוכלו להשתמש בתבנית המודול של Macrobenchmark ובפלאגין Gradle של Baseline Profile כדי ליצור Baseline Profile חדש. מומלץ להשתמש בכלים האלה החל מ-Android Studio Giraffe ו-AGP 8.1.

כך יוצרים פרופיל בסיס חדש באמצעות התבנית של מודול Macrobenchmark והפלאגין של Baseline Profile ב-Gradle:

  1. מגדירים מודול Macrobenchmark בפרויקט Gradle.
  2. מגדירים מחלקה חדשה בשם BaselineProfileGenerator:
    class BaselineProfileGenerator {
        @get:Rule
        val baselineProfileRule = BaselineProfileRule()
    
        @Test
        fun startup() = baselineProfileRule.collect(
            packageName = "com.example.app",
            profileBlock = {
                startActivityAndWait()
            }
        )
    }

    הגנרטור יכול לכלול אינטראקציות עם האפליקציה מעבר להפעלה שלה. כך תוכלו לבצע אופטימיזציה של ביצועי האפליקציה בסביבת זמן הריצה, למשל גלילה ברשימות, הפעלת אנימציות וניווט בתוך Activity. כאן תוכלו למצוא דוגמאות נוספות לבדיקות שמשתמשות ב-@BaselineProfileRule כדי לשפר תהליכי שימוש קריטיים.

  3. מוסיפים את הפלאגין Baseline Profile Gradle‏ (libs.plugins.androidx.baselineprofile). הפלאגין מקל על יצירת פרופילים בסיסיים ועל ניהול שלהם בעתיד.

  4. כדי ליצור את פרופיל הבסיס, מריצים את המשימות :app:generateBaselineProfile או :app:generateVariantBaselineProfile של Gradle בטרמינל.

    מריצים את ה-generator כבדיקה עם מכשירי מעקב במכשיר פיזי עם הרשאת Root, באמולטור או במכשיר בניהול Gradle. אם אתם משתמשים במכשיר שמנוהל על ידי Gradle, צריך להגדיר את aosp בתור systemImageSource, כי צריך הרשאת root ליצירת הפרופיל הבסיסי.

    בסיום המשימה ליצירת הפרופיל, פרופיל הבסיס יועתק אל app/src/variant/generated/baselineProfiles.

יצירת פרופיל בסיס חדש ללא תבניות

מומלץ ליצור פרופיל Baseline באמצעות התבנית של מודול Baseline Profile ב-Android Studio (האפשרות המועדפת) או באמצעות התבנית של Macrobenchmark, אבל אפשר גם להשתמש בפלאגין Baseline Profile ב-Gradle בפני עצמו. מידע נוסף על הפלאגין של Gradle לפרופיל הבסיס זמין במאמר הגדרת היצירה של פרופיל הבסיס.

כך יוצרים פרופיל Baseline ישירות באמצעות הפלאגין של Baseline Profile ב-Gradle:

  1. יוצרים מודול com.android.test חדש, למשל :baseline-profile.
  2. מגדירים את הקובץ build.gradle.kts עבור :baseline-profile:

    1. מחילים את הפלאגין androidx.baselineprofile.
    2. מוודאים שה-targetProjectPath מפנה למודול :app.
    3. אפשר גם להוסיף מכשיר בניהול Gradle‏ (GMD). בדוגמה הבאה, הערך הוא pixel6Api31. אם לא צוין, הפלאגין ישתמש במכשיר מחובר, שהוא מכשיר פיזי או מכשיר ממולא.
    4. מחילים את ההגדרה הרצויה, כפי שמתואר בדוגמה הבאה.

    Kotlin

    plugins {
        id("com.android.test")
        id("androidx.baselineprofile")
    }
    
    android {
        defaultConfig {
            ...
        }
    
        // Point to the app module, the module that you're generating the Baseline Profile for.
        targetProjectPath = ":app"
        // Configure a GMD (optional).
        testOptions.managedDevices.devices {
            pixel6Api31(com.android.build.api.dsl.ManagedVirtualDevice) {
                device = "Pixel 6"
                apiLevel = 31
                systemImageSource = "aosp"
            }
        }
    }
    
    dependencies { ... }
    
    // Baseline Profile Gradle plugin configuration. Everything is optional. This
    // example uses the GMD added earlier and disables connected devices.
    baselineProfile {
        // Specifies the GMDs to run the tests on. The default is none.
        managedDevices += "pixel6Api31"
        // Enables using connected devices to generate profiles. The default is
        // `true`. When using connected devices, they must be rooted or API 33 and
        // higher.
        useConnectedDevices = false
    }

    Groovy

    plugins {
        id 'com.android.test'
        id 'androidx.baselineprofile'
    }
    
    android {
        defaultConfig {
            ...
        }
    
        // Point to the app module, the module that you're generating the Baseline Profile for.
        targetProjectPath ':app'
        // Configure a GMD (optional).
        testOptions.managedDevices.devices {
            pixel6Api31(com.android.build.api.dsl.ManagedVirtualDevice) {
                device 'Pixel 6'
                apiLevel 31
                systemImageSource 'aosp'
            }
        }
    }
    
    dependencies { ... }
    
    // Baseline Profile Gradle plugin configuration. Everything is optional. This
    // example uses the GMD added earlier and disables connected devices.
    baselineProfile {
        // Specifies the GMDs to run the tests on. The default is none.
        managedDevices ['pixel6Api31']
        // Enables using connected devices to generate profiles. The default is
        // `true`. When using connected devices, they must be rooted or API 33 and
        // higher.
        useConnectedDevices false
    }
  3. יוצרים בדיקה של פרופיל בסיס במודול הבדיקה :baseline-profile. הדוגמה הבאה היא בדיקה שמפעילה את האפליקציה ומחכה למצב חוסר פעילות.

    Kotlin

    class BaselineProfileGenerator {
    
        @get:Rule
        val baselineRule = BaselineProfileRule()
    
        @Test
        fun startupBaselineProfile() {
            baselineRule.collect("com.myapp") {
                startActivityAndWait()
            }
        }
    }

    Java

    public class BaselineProfileGenerator {
    
        @Rule
        Public BaselineProfileRule baselineRule = new BaselineProfileRule();
    
        @Test
        Public void startupBaselineProfile() {
            baselineRule.collect(
                "com.myapp",
                (scope -> {
                    scope.startActivityAndWait();
                    Return Unit.INSTANCE;
                })
            )
        }
    }
  4. מעדכנים את הקובץ build.gradle.kts במודול של האפליקציה, למשל :app.

    1. מחילים את הפלאגין androidx.baselineprofile.
    2. מוסיפים יחסי תלות של baselineProfile למודול :baseline-profile.

    Kotlin

    plugins {
        id("com.android.application")
        id("androidx.baselineprofile")
    }
    
    android {
        // There are no changes to the `android` block.
        ...
    }
    
    dependencies {
        ...
        // Add a `baselineProfile` dependency on the `:baseline-profile` module.
        baselineProfile(project(":baseline-profile"))
    }

    Groovy

    plugins {
        id 'com.android.application'
        id 'androidx.baselineprofile'
    }
    
    android {
        // No changes to the `android` block.
        ...
    }
    
    dependencies {
        ...
        // Add a `baselineProfile` dependency on the `:baseline-profile` module.
        baselineProfile ':baseline-profile'
    }
  5. כדי ליצור את הפרופיל, מריצים את המשימות :app:generateBaselineProfile או :app:generateVariantBaselineProfile ב-Gradle.

  6. בסיום המשימה ליצירת הפרופיל, פרופיל הבסיס יועתק אל app/src/variant/generated/baselineProfiles.

יצירת פרופיל בסיס חדש באמצעות AGP 7.3-7.4

אפשר ליצור פרופילים בסיסיים באמצעות AGP בגרסאות 7.3 עד 7.4, אבל מומלץ מאוד לשדרג ל-AGP בגרסה 8.1 לפחות כדי שתוכלו להשתמש בפלאגין של Baseline Profile ב-Gradle ובתכונות העדכניות ביותר שלו.

אם אתם צריכים ליצור פרופילים בסיסיים באמצעות AGP 7.3-7.4, השלבים זהים לשלבים ל-AGP 8.1, עם ההחרגות הבאות:

החלה ידנית של כללים שנוצרו

הכלי ליצירת פרופיל בסיס יוצר קובץ טקסט בפורמט קריא לבני אדם (HRF) במכשיר ומעתיק אותו למכונה המארחת. כדי להחיל את הפרופיל שנוצר על הקוד, פועלים לפי השלבים הבאים:

  1. מאתרים את קובץ ה-HRF בתיקיית ה-build של המודול שבו יוצרים את הפרופיל: [module]/build/outputs/managed_device_android_test_additional_output/[device].

    שמות הפרופילים מורכבים לפי התבנית [class name]-[test method name]-baseline-prof.txt, שנראית כך:BaselineProfileGenerator-startup-baseline-prof.txt.

  2. מעתיקים את הפרופיל שנוצר אל src/main/ ומשנים את שם הקובץ ל-baseline-prof.txt.

  3. כדי לאפשר הידור מקומי של פרופיל בסיס, מוסיפים יחסי תלות לספריית ProfileInstaller בקובץ build.gradle.kts של האפליקציה, במקרים שבהם פרופילים ב-Cloud לא זמינים. זוהי הדרך היחידה להעלות פרופיל Baseline באופן מקומי.

    dependencies {
         implementation("androidx.profileinstaller:profileinstaller:1.4.1")
    }
    
  4. יוצרים את גרסת הייצור של האפליקציה בזמן שכללי HRF שמופעלים מקובצים לפורמט בינארי ונכללים ב-APK או ב-AAB. לאחר מכן, אפשר להפיץ את האפליקציה כרגיל.

השוואה של פרופיל Baseline לפרופיל אחר

כדי ליצור את נקודת השוואה לפרופיל הבסיס, יוצרים הגדרה חדשה של Android Instrumented Test Run מהפעולה בסרגל הצד, שמפעילה את נקודות השוואה שהוגדרו בקובץ StartupBenchmarks.kt או בקובץ StartupBencharks.java. מידע נוסף על בדיקת ביצועים זמין במאמרים יצירת כיתה של Macrobenchmark ואוטומציה של המדידה באמצעות ספריית Macrobenchmark.

איור 3. מריצים את בדיקות Android מהפעולה שבשולי המסך.

כשמריצים את הפקודה הזו ב-Android Studio, פלט ה-build מכיל פרטים על שיפורי המהירות שמתקבלים מפרופיל הבסיס:

StartupBenchmarks_startupCompilationBaselineProfiles
timeToInitialDisplayMs   min 161.8,   median 178.9,   max 194.6
StartupBenchmarks_startupCompilationNone
timeToInitialDisplayMs   min 184.7,   median 196.9,   max 202.9

תיעוד כל נתיבי הקוד הנדרשים

שני מדדי המפתח למדידת זמני ההפעלה של האפליקציה הם:

זמן להצגה ראשונית (TTID)
הזמן שחולף עד להצגת הפריים הראשון של ממשק המשתמש של האפליקציה.
זמן להצגה מלאה (TTFD)
TTID בתוספת הזמן להצגת תוכן שנטען באופן אסינכרוני אחרי הצגת הפריים הראשוני.

הדיווח על זמן אחזור יעד מתבצע לאחר הקריאה לשיטה reportFullyDrawn() של ComponentActivity. אם לא קוראים ל-reportFullyDrawn() אף פעם, ה-TTID ידווח במקום זאת. יכול להיות שתצטרכו לדחות את הקריאה ל-reportFullyDrawn() עד שהטעינה האסינכרונית תושלם. לדוגמה, אם ממשק המשתמש מכיל רשימה דינמית כמו RecyclerView או רשימה עצלה, יכול להיות שהרשימה תתמלא על ידי משימה ברקע שתסתיים אחרי שהרשימה תתואר בפעם הראשונה, ולכן אחרי שממשק המשתמש מסומן כמתואר במלואו. במקרים כאלה, קוד שפועל אחרי שממשק המשתמש מגיע למצב שבו הוא מצויר במלואו לא נכלל בפרופיל הבסיס.

כדי לכלול את אוכלוסיית הרשימה כחלק מפרופיל הבקרה, צריך לקבל את הערך של FullyDrawnReporter באמצעות getFullyDrawnReporter() ולהוסיף לו מדווח בקוד האפליקציה. משחררים את הדיווח אחרי שהמשימה ברקע מסיימת לאכלס את הרשימה. ה-FullyDrawnReporter לא קורא לשיטה reportFullyDrawn() עד שכל הדיווחים משוחררים. כך, פרופיל הבקרה יכלול את נתיבי הקוד הנדרשים כדי לאכלס את הרשימה. הפעולה הזו לא משנה את התנהגות האפליקציה עבור המשתמש, אבל היא מאפשרת לפרופיל הבסיס לכלול את כל נתיבי הקוד הנדרשים.

אם באפליקציה שלכם נעשה שימוש ב-Jetpack Compose, תוכלו להשתמש בממשקי ה-API הבאים כדי לציין מצב שבו התמונה צוירה במלואה:

  • ReportDrawn מציינת שהרכיב המודולרי מוכן מיד לאינטראקציה.
  • ReportDrawnWhen מקבלת תנאי, כמו list.count > 0, כדי לציין מתי הרכיב הניתן לקישור מוכן לאינטראקציה.
  • ReportDrawnAfter מקבלת שיטה להשהיה, שבסיום שלה מציינת שהרכיב ה-Composable מוכן לאינטראקציה.