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

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

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

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

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

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

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

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

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

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

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

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

    • אפליקציית היעד: מגדירה לאיזו אפליקציה המערכת תיצור את פרופיל הבקרה. אם יש לכם רק מודול אפליקציה אחד בפרויקט, יופיע רק פריט אחד ברשימה הזו.
    • שם המודול: השם שרוצים למודול של פרופיל הבסיס שנוצר.
    • Package name: שם החבילה הרצוי למודול של פרופיל הבסיס.
    • 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 (יצירת פרופיל Baseline), מתבצעת העתקה של פרופיל הבסיס שנוצר לקובץ 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

אם אתם לא יכולים להשתמש בתבנית המודול של פרופיל הבסיס, תוכלו להשתמש בתבנית המודול של Macrobenchmark ובפלאגין Baseline Profile Gradle כדי ליצור פרופיל Baseline חדש. מומלץ להשתמש בכלים האלה החל מ-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. מוסיפים את הפלאגין Gradle של Baseline Profile (libs.plugins.androidx.baselineprofile). הפלאגין מקל על יצירת פרופילים בסיסיים ועל ניהול שלהם בעתיד.

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

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

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

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

מומלץ ליצור פרופיל Baseline באמצעות תבנית המודול של פרופיל Baseline ל-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"))
    }

    מגניב

    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 לפחות כדי להשתמש בפלאגין של Gradle ב-Baseline Profile ובתכונות האחרונות שלו.

אם אתם צריכים ליצור פרופילים בסיסיים באמצעות 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 משתמשת בשיטת השעיה, שבסיום הפעולה שלה מצוין שהתוכן הקומפוזבילי מוכן לאינטראקציה.