יצירת פרופיל ה-build

בפרויקטים גדולים יותר או בכאלה שמיישמים הרבה לוגיקת build מותאמת אישית, מחייבים אתכם לבחון לעומק את תהליך ה-build כדי למצוא צווארי בקבוק. תוכלו לעשות את זה על ידי יצירת פרופיל של כמה זמן ייקח ל-Gradle לבצע כל שלב ב- את מחזור החיים של ה-build וכל משימת build. לדוגמה, אם פרופיל ה-build שלך מראים ש-Gradle משקיע יותר מדי זמן בהגדרת הפרויקט, העברת לוגיקת build מותאמת אישית משלב התצורה. בנוסף, אם המשימה mergeDevDebugResources צורכת כמות גדולה זמן ה-build, המרת התמונות ל-WebP או השבתה של דחיסת קובצי PNG.

אם אתם משתמשים Android Studio מגרסה 4.0 ואילך, הדרך הטובה ביותר לחקור את ביצועי ה-build היא על ידי שימוש ב-Build Analyzer.

בנוסף, יש שתי אפשרויות ליצירת פרופילים של ה-build מחוץ ל- Android Studio:

  1. הכלי gradle-profiler העצמאי, כלי עוצמתי לניתוח מעמיק של ה-build שלך.

  2. האפשרות Gradle --profile, כלי נוח שזמין משורת הפקודה Gradle.

שימוש בכלי הנפרד gradle-profiler

כדי למצוא את הגדרת הפרויקט שמספקת לכם את מהירות ה-build הטובה ביותר, צריך להשתמש ב-Gradle profiler, כלי לאיסוף מידע על פרופילים והשוואה לשוק של Gradle build. הכלי ליצירת פרופיל של Gradle מאפשר ליצור תרחישים של build ולהריץ אותם פעמים רבות, כדי למנוע שונות גבוהה של התוצאות ולוודא יכולת שחזור בין התוצאות.

מצב השוואה לשוק יכול לשמש לאיסוף מידע על גרסאות build נקיות והדרגתיות, בזמן מצב פרופיילינג יכול לשמש לאיסוף מידע מפורט יותר על ההפעלות, כולל המעבד (CPU) קובצי snapshot.

אלה כמה מההגדרות של הגדרת הפרויקט להשוואה לשוק:

  • גרסאות פלאגין
  • גרסאות של Gradle
  • הגדרות JVM (גודל ערימה, גודל קבוע, איסוף אשפה וכו')
  • מספר העובדים ב-Gradle (org.gradle.workers.max)
  • אפשרויות לכל פלאגין לביצוע אופטימיזציה נוספת של הביצועים

תחילת העבודה

  • כדי להתקין את gradle-profiler, צריך לפעול לפי ההוראות האלה.
  • הפעלה: gradle-profiler --benchmark --project-dir <root-project> :app:assembleDebug

זו השוואה לשוק של build עדכני לחלוטין מפני ש---benchmark מפעיל את משימה מספר פעמים, בלי לשנות את הפרויקט ביניהם. לאחר מכן היא ליצור דוח HTML בספרייה profile-out/ שמראה זמני פיתוח.

יש תרחישים אחרים שעשויים להיות שימושיים יותר כנקודת השוואה:

  • שינויים בקוד בגוף השיטה בכיתה שבה אתם מבצעים את רוב העבודה.
  • שינויים ב-API במודול שבו משתמשים בכל הפרויקט. אומנם פחות מאשר שינויים בקוד שלכם, יש לכך השפעה גדולה יותר שימושי כדי למדוד אותה.
  • עריכת פריסה שנועדה לדמות חזרה לעבודה בממשק המשתמש.
  • עריכות מחרוזות שמדמות התמודדות עם עבודת תרגום.
  • גרסאות build נקיות שמדמות שינויים ב-build עצמו (למשל, גרדל Android עדכון יישומי פלאגין, עדכון Gradle או עריכות בקוד build משלך מתחת ל-buildSrc).

כדי ליצור נקודת השוואה לתרחישים לדוגמה האלו, אפשר ליצור תרחיש ששימשו לביצוע ההפעלה של gradle-profiler והחלה לשינויים במקורות שלכם. בהמשך אפשר לראות כמה מהתרחישים הנפוצים.

יצירת פרופילים עם הגדרות שונות של זיכרון/מעבד (CPU)

כדי להשוות להגדרות שונות של זיכרון ומעבד (CPU), אפשר ליצור תרחישים מרובים שמשתמשים בערכים שונים עבור org.gradle.jvmargs. עבור לדוגמה, אפשר ליצור תרחישים:

# <root-project>/scenarios.txt
clean_build_2gb_4workers {
    tasks = [":app:assembleDebug"]
    gradle-args = ["--max-workers=4"]
    jvm-args = ["-Xmx2048m"]
    cleanup-tasks = ["clean"]
}
clean_build_parallelGC {
    tasks = [":app:assembleDebug"]
    jvm-args = ["-XX:+UseParallelGC"]
    cleanup-tasks = ["clean"]
}

clean_build_G1GC_4gb {
    tasks = [":app:assembleDebug"]
    jvm-args = ["-Xmx4096m", "-XX:+UseG1GC"]
    cleanup-tasks = ["clean"]
}

מריץ gradle-profiler --benchmark --project-dir <root-project> --scenario-file scenarios.txt להריץ שלושה תרחישים, ותוכלו להשוות :app:assembleDebug לוקחים לכל אחת מהתצורות האלה.

יצירת פרופילים בגרסאות שונות של יישומי פלאגין של Gradle

כדי להבין איך שינוי גרסת הפלאגין של Gradle משפיע זמני build, ליצור תרחיש לצורך השוואה לשוק. לשם כך נדרשים כדי להפוך את גרסת הפלאגין לניתנת להחדרה מהתרחיש. שינוי build.gradle:

# <root-project>/build.gradle
buildscript {
    def agpVersion = providers.systemProperty("agpVersion").forUseAtConfigurationTime().orNull ?: '4.1.0'

    ext.kotlin = providers.systemProperty('kotlinVersion').forUseAtConfigurationTime().orNull ?: '1.4.0'

    dependencies {
        classpath "com.android.tools.build:gradle:$agpVersion"
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin"
    }
}

עכשיו אפשר לציין את הפלאגין ל-Android Gradle ואת הפלאגין Kotlin Gradle מגרסה חדשה מקובץ התרחישים, ולבקש מהתרחיש להוסיף שיטה חדשה קובצי המקור:

# <root-project>/scenarios.txt
non_abi_change_agp4.1.0_kotlin1.4.10 {
    tasks = [":app:assembleDebug"]
    apply-abi-change-to ["app/src/main/java/com/example/your_app/your_code_file.java,
                              "app/src/main/java/com/example/your_app/your_code_file.kt"]
    System-properties {
      "agpVersion" = "4.1.0"
      "kotlinVersion" = "1.4.10"
}

non_abi_change_agp4.2.0_kotlin1.4.20 {
    tasks = [":app:assembleDebug"]
    apply-abi-change-to ["app/src/main/java/com/example/your_app/your_code_file.java,
                              "app/src/main/java/com/example/your_app/your_code_file.kt"]
    System-properties {
      "agpVersion" = "4.2.0-alpha16"
      "kotlinVersion" = "1.4.20"
}

יצירת פרופילים של גרסת build מצטברת

רוב גרסאות ה-build הן מצטברות, וזה אחד מהגרסאות החשובות ביותר לפרופילים. בכלי ליצירת פרופיל ב-Gradle יש תמיכה רחבה יצירת פרופילים של גרסאות build מצטברות. יש לו אפשרות להחיל שינויים על קובץ מקור באופן אוטומטי על ידי שינוי גוף השיטה, הוספת method חדשה או שינוי משאב של פריסה או מחרוזת. עבור תוכלו ליצור תרחישים מצטברים כמו:

# <root-project>/scenarios.txt
non_abi_change {
    tasks = [":app:assembleDebug"]
    apply-non-abi-change-to = ["app/src/main/java/com/example/your_app/your_code_file.java,
                              "app/src/main/java/com/example/your_app/your_code_file.kt"]
}

abi_change {
    tasks = [":app:assembleDebug"]
    apply-abi-change-to = ["app/src/main/java/com/example/your_app/your_code_file.java,
                              "app/src/main/java/com/example/your_app/your_code_file.kt"]
}

layout_change {
    tasks = [":app:assembleDebug"]
    apply-android-layout-change-to = "app/src/main/res/your_layout_file.xml"
}
string_resource_change {
    tasks = [":app:assembleDebug"]
    apply-android-resource-value-change-to = "app/src/main/res/values/strings.xml"
}

מריץ gradle-profiler --benchmark --project-dir &lt;root-project> --scenario-file scenarios.txt תפיק את דוח ה-HTML עם נתוני ההשוואה לשוק.

אפשר לשלב תרחישים מצטברים עם הגדרות אחרות, כמו גודל הזיכרון, מספר העובדים, או גרסת Gradle:

# <root-project>/scenarios.txt
non_abi_change_4g {
    tasks = [":app:assembleDebug"]
    apply-non-abi-change-to ["app/src/main/java/com/example/your_app/your_code_file.java,
                              "app/src/main/java/com/example/your_app/your_code_file.kt"]
    jvm-args = ["-Xmx4096m"]
}

non_abi_change_4g_8workers {
    tasks = [":app:assembleDebug"]
    apply-non-abi-change-to ["app/src/main/java/com/example/your_app/your_code_file.java,
                              "app/src/main/java/com/example/your_app/your_code_file.kt"]
    jvm-args = ["-Xmx4096m"]
    gradle-args = ["--max-workers=8"]
}

non_abi_change_3g_gradle67 {
    tasks = [":app:assembleDebug"]
    apply-non-abi-change-to ["app/src/main/java/com/example/your_app/your_code_file.java,
                              "app/src/main/java/com/example/your_app/your_code_file.kt"]
    jvm-args = ["-Xmx3072m"]
    version = ["6.7"]
}

יצירת פרופילים של build נקי

כדי ליצור נקודת השוואה של build נקי, אפשר ליצור תרחיש ששימשו לביצוע הביצוע של gradle-profiler:

# <root-project>/scenarios.txt
clean_build {
    tasks = [":app:assembleDebug"]
    cleanup-tasks = ["clean"]
}

כדי להריץ את התרחיש הזה, משתמשים בפקודה הבאה:

gradle-profiler --benchmark --project-dir <root-project> --scenario-file scenarios.txt

שימוש באפשרות Gradle --profile

כדי ליצור ולהציג פרופיל build משורת הפקודה של Gradle, מבצעים את הפעולות הבאות: את השלבים הבאים:

  1. פותחים טרמינל של שורת פקודה ברמה הבסיסית (root) של הפרויקט.
  2. כדי לבצע build נקי, מזינים את הפקודה הבאה. בפרופיל שלך צריך לבצע build נקי בין כל גרסאות build כי Gradle מדלגת על משימות כשקלט של משימה (כמו קוד מקור) לא שינוי. כך, build שני ללא שינויים בקלט תמיד פועל מהר יותר משימות שונות לא מבוצעות מחדש. לכן נריץ את המשימה clean בין כדי שתוכלו ליצור פרופיל עסק מלא של ה-build.
    // On Mac or Linux, run the Gradle wrapper using "./gradlew".
    gradlew clean
    
  3. להפעיל build לניפוי באגים עבור אחד מסוגי המוצרים שלכם, כגון 'dev' טעם, עם הדגלים הבאים:
    gradlew --profile --offline --rerun-tasks assembleFlavorDebug
    
    • --profile: הפעלת הפרופיילינג.
    • --offline: השבתה של Gradle לאחזור אונליין של יחסי התלות. זה עוזר למנוע עיכובים ככל האפשר מ-Gradle הניסיון לעדכן את יחסי התלות לא יפריעו של נתוני הפרופיילינג. כבר הייתם אמורים לבנות את הפרויקט פעם אחת כדי לוודא ש-Gradle כבר הוריד ושמר את יחסי התלות במטמון.
    • --rerun-tasks: כך מאלצים את Gradle להריץ מחדש את כל המשימות ולתעלם כל אופטימיזציה של משימה.
  4. איור 1. תצוגת פרויקט שמציינת את המיקום של דוחות פרופיל.

    בסיום ה-build, עוברים אל החלון Project ספריית project-root/build/reports/profile/ (כ שמוצגת באיור 1).

  5. לוחצים לחיצה ימנית על הקובץ profile-timestamp.html ובוחרים פתח בדפדפן > ברירת מחדל. הדוח צריך להיות דומה לזה שמוצגת באיור 2. אפשר לבחון כל כרטיסייה בדוח כדי לקבל מידע נוסף build, כמו הכרטיסייה ביצוע משימות, שמראה כמה זמן לקח ל-Gradle כדי לבצע כל משימת build.

    איור 2. הצגת דוח בדפדפן.

  6. אופציונלי: לפני שמבצעים שינויים בפרויקט או ב-build וחוזרים על הפקודה בשלב 3, להשמיט את דגל --rerun-tasks. כי Gradle מנסה לחסוך זמן לבצע מחדש משימות שהקלט לא השתנה (כלומר UP-TO-DATE בכרטיסייה ביצוע משימה בדוח, כפי שמוצג בתרשים 3), תוכלו לזהות אילו משימות מניבות תוצאות לא צריכה להיות. לדוגמה, אם :app:processDevUniversalDebugManifest לא מסומן בתור UP-TO-DATE, יכול להיות שהגדרות ה-build שלך הן עדכון דינמי של המניפסט בכל build. אבל, חלק מהמשימות שמריצים בכל שלב build, למשל :app:checkDevDebugManifest.

    איור 3. הצגת תוצאות של ביצוע משימות.

עכשיו, כשיש לך דוח פרופיל build, אפשר להתחיל לחפש לשיפור האופטימיזציה על ידי בדיקת המידע בכל כרטיסייה שלנו. חלק מהגדרות ה-build מחייבות ניסוי מפני שהיתרונות עשויים שונות בין פרויקטים לתחנות עבודה. לדוגמה, פרויקטים עם כמות גדולה של codebase יכול להפיק תועלת מכיווץ קוד. כדי להסיר קוד שלא נמצא בשימוש ולכווץ את גודל האפליקציה. אבל קטן יותר פרויקטים יכולים להפיק תועלת רבה יותר מהשבתה מלאה של כיווץ הקוד. בנוסף, הגדלת גודל הערימה של Gradle (באמצעות org.gradle.jvmargs) עלול להשפיע לרעה על הביצועים במכונות עם נפח זיכרון נמוך.

אחרי שמשנים את תצורת ה-build, כדאי לצפות בתוצאות של חוזרים על השלבים שלמעלה ויוצרים פרופיל build חדש. לדוגמה, איור 4 מציג דוח עבור אותה אפליקציה לדוגמה אחרי ההחלה חלק מהאופטימיזציות הבסיסיות המתוארות בדף זה.

איור 4. צפייה בדוח חדש אחרי ביצוע אופטימיזציה של ה-build המהירות שלו.