כדי לבדוק תרחישי שימוש גדולים יותר באפליקציה, כולל הפעלה של האפליקציה ומניפולציות מורכבות בממשק המשתמש, כמו גלילה בRecyclerView
או הפעלת אנימציות, אפשר להשתמש בספריית Macrobenchmark. אם רוצים לבדוק אזורים קטנים יותר בקוד, אפשר להיעזר בספריית Microbenchmark. בדף הזה מוסבר איך להגדיר את ספריית Macrobenchmark.
הספרייה מפיקה תוצאות השוואה לביצועים גם במסוף של Android Studio וגם בקובץ JSON עם פרטים נוספים. הוא גם מספק קבצים של נתוני מעקב שאפשר לטעון ולנתח ב-Android Studio.
שימוש בספריית Macrobenchmark בסביבת אינטגרציה רציפה (CI), כמו שמתואר במאמר Benchmark in Continuous Integration.
אפשר להשתמש ב-Macrobenchmark כדי ליצור פרופילים של קו בסיס. קודם מגדירים את ספריית Macrobenchmark, ואז אפשר ליצור פרופיל בסיסי.
הגדרת הפרויקט
מומלץ להשתמש ב-Macrobenchmark עם הגרסה העדכנית של Android Studio כדי ליהנות מתכונות של סביבת הפיתוח המשולבת שמשולבות עם Macrobenchmark.
הגדרת מודול Macrobenchmark
בדיקות מאקרו דורשות מודול com.android.test
נפרד מקוד האפליקציה, שאחראי להרצת הבדיקות שמודדות את האפליקציה.
ב-Android Studio יש תבנית שמאפשרת להגדיר מודול Macrobenchmark בקלות. תבנית מודול ההשוואה יוצרת באופן אוטומטי מודול בפרויקט שלכם למדידת האפליקציה שנבנתה על ידי מודול האפליקציה, כולל מדד השוואה לדוגמה של זמן ההפעלה.
כדי להשתמש בתבנית של מודול כדי ליצור מודול חדש:
לוחצים לחיצה ימנית על הפרויקט או המודול בחלונית Project ב-Android Studio ובוחרים באפשרות New > Module (חדש > מודול).
בוחרים באפשרות השוואה לשוק בחלונית תבניות. אפשר להתאים אישית את אפליקציית היעד – כלומר, האפליקציה שרוצים להשוות לביצועים של אפליקציות אחרות – וגם את שם החבילה והמודול של מודול Macrobenchmark החדש.
לוחצים על סיום.
איור 1. תבנית של מודול השוואה לשוק.
הגדרת האפליקציה
כדי להשוות בין אפליקציות – מה שנקרא יעד של Macrobenchmark – האפליקציה צריכה להיות profileable
, מה שמאפשר לקרוא מידע מפורט על המעקב בלי להשפיע על הביצועים. אשף המודולים מוסיף את תג <profileable>
באופן אוטומטי לקובץ AndroidManifest.xml
של האפליקציה.
מוודאים שאפליקציית היעד כוללת את ProfilerInstaller
גרסה 1.3 ומעלה, שספריית Macrobenchmark צריכה כדי להפעיל את לכידת הפרופיל, האיפוס והניקוי של מטמון ההצללה.
כדאי להגדיר את האפליקציה להשוואה כמה שיותר קרוב לגרסת הפרסום או לגרסת הייצור. מומלץ להגדיר אותו כלא ניתן לניפוי באגים, ועדיף להפעיל בו מיניפיקציה כדי לשפר את הביצועים. בדרך כלל עושים את זה על ידי יצירת עותק של גרסת ההפצה, שמבצעת את אותה פעולה, אבל חותמת באופן מקומי באמצעות מפתחות ניפוי באגים.
אפשר גם להשתמש ב-initWith
כדי להנחות את Gradle לעשות זאת בשבילכם:
Kotlin
buildTypes { getByName("release") { isMinifyEnabled = true isShrinkResources = true proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt")) } create("benchmark") { initWith(getByName("release")) signingConfig = signingConfigs.getByName("debug") } }
Groovy
buildTypes { getByName("release") { isMinifyEnabled = true isShrinkResources = true proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro" ) // In real app, this would use its own release keystore signingConfig = signingConfigs.getByName("debug") } }
כדי לוודא שהפעלת ההשוואה תבנה ותבדוק את הווריאנט הנכון של האפליקציה, כמו שמוצג באיור 2, צריך לבצע את הפעולות הבאות:
- מבצעים סנכרון של Gradle.
- פותחים את החלונית Build Variants.
- בוחרים את וריאציית ההשוואה לשוק של האפליקציה ושל מודול Macrobenchmark.
איור 2. בוחרים את וריאציית ההשוואה.
(אופציונלי) הגדרת אפליקציה עם כמה מודולים
אם לאפליקציה יש יותר ממודול Gradle אחד, צריך לוודא שסקריפטים ה-build יודעים איזו גרסת build לקמפל. מוסיפים את המאפיין matchingFallbacks
לסוג ה-build של מודולי :macrobenchmark
ו-:app
.benchmark
שאר מודולי Gradle יכולים להיות עם אותה הגדרה כמו קודם.
Kotlin
create("benchmark") { initWith(getByName("release")) signingConfig = signingConfigs.getByName("debug") matchingFallbacks += listOf("release") }
Groovy
benchmark { initWith buildTypes.release signingConfig signingConfigs.debug matchingFallbacks = ['release'] }
בלי זה, סוג ה-build החדש שנוסף benchmark
גורם ל-build להיכשל
ומוצגת הודעת השגיאה הבאה:
> Could not resolve project :shared.
Required by:
project :app
> No matching variant of project :shared was found.
...
כשבוחרים את וריאציות ה-build בפרויקט, בוחרים באפשרות benchmark
עבור המודולים :app
ו-:macrobenchmark
, ובאפשרות release
עבור כל מודול אחר שיש באפליקציה, כמו שמוצג באיור 3:
איור 3. השוואת ביצועים בין וריאציות של פרויקט מרובה מודולים עם סוגי build של גרסת פרסום והשוואת ביצועים.
מידע נוסף מפורט במאמר בנושא שימוש בניהול תלויות עם מודעות לווריאציות.
(אופציונלי) הגדרת טעמים של מוצרים
אם הגדרתם באפליקציה כמה טעמים של מוצרים, צריך להגדיר את מודול :macrobenchmark
כדי שידע איזה טעם של מוצר לבנות ולמדוד.
בדוגמאות שבדף הזה נעשה שימוש בשני טעמי המוצר במודול :app
: demo
ו-production
, כמו שמוצג בקטע הקוד הבא:
Kotlin
flavorDimensions += "environment" productFlavors { create("demo") { dimension = "environment" // ... } create("production") { dimension = "environment" // ... } }
Groovy
flavorDimensions 'environment' productFlavors { demo { dimension 'environment' // ... } production { dimension 'environment' // ... } }
בלי ההגדרה הזו, יכול להיות שתקבלו שגיאת build דומה לזו שמתקבלת עם כמה מודולים של Gradle:
Could not determine the dependencies of task ':macrobenchmark:connectedBenchmarkAndroidTest'.
> Could not determine the dependencies of null.
> Could not resolve all task dependencies for configuration ':macrobenchmark:benchmarkTestedApks'.
> Could not resolve project :app.
Required by:
project :macrobenchmark
> The consumer was configured to find a runtime of a component, as well as attribute 'com.android.build.api.attributes.BuildTypeAttr' with value 'benchmark', attribute 'com.android.build.api.attributes.AgpVersionAttr' with value '7.3.0'. However we cannot choose between the following variants of project :app:
- demoBenchmarkRuntimeElements
- productionBenchmarkRuntimeElements
All of them match the consumer attributes:
...
בקטעים הבאים מוסבר איך להגדיר השוואה לשוק עם כמה גרסאות של מוצרים.
שימוש ב-missingDimensionStrategy
אם מציינים missingDimensionStrategy
ב-defaultConfig
של המודול :macrobenchmark
, מערכת ה-build יודעת לחזור למאפיין flavor. אם לא מוצאים את המאפיינים במודול, צריך לציין באילו מאפיינים להשתמש.
בדוגמה הבאה, הטעם production
משמש כמאפיין ברירת המחדל:
Kotlin
defaultConfig { missingDimensionStrategy("environment", "production") }
Groovy
defaultConfig { missingDimensionStrategy "environment", "production" }
כך, מודול :macrobenchmark
יכול ליצור ולמדוד רק את טעם המוצר שצוין, וזה שימושי אם אתם יודעים שלטעם מוצר אחד בלבד יש את ההגדרה המתאימה למדידה.
הגדרת טעמי מוצר במודול :macrobenchmark
אם רוצים ליצור טעמים אחרים של מוצרים ולהשוות ביניהם, צריך להגדיר אותם במודול :macrobenchmark
. מציינים אותו באופן דומה כמו במודול :app
, אבל מקצים רק את productFlavors
ל-dimension
. אין צורך בהגדרות נוספות:
Kotlin
flavorDimensions += "environment" productFlavors { create("demo") { dimension = "environment" } create("production") { dimension = "environment" } }
Groovy
flavorDimensions 'environment' productFlavors { demo { dimension 'environment' } production { dimension 'environment' } }
אחרי שמגדירים ומסנכרנים את הפרויקט, בוחרים את וריאציית ה-build הרלוונטית בחלונית Build Variants, כמו שמוצג באיור 4:
איור 4. השוואה בין וריאציות של המוצר בפרויקט עם טעמי מוצר שמוצגים, כשהאפשרויות 'productionBenchmark' ו-'release' מסומנות.
מידע נוסף זמין במאמר פתרון שגיאות שקשורות להתאמת וריאציות.
יצירת מחלקה של בדיקת ביצועים
בדיקות השוואה לביצועים מסופקות באמצעות כלל MacrobenchmarkRule
JUnit4 API בספריית Macrobenchmark. הוא מכיל את השיטה measureRepeated
שמאפשרת לציין תנאים שונים להפעלה של אפליקציית היעד ולביצוע השוואה בין ביצועיה לבין ביצועי אפליקציות אחרות.
צריך לציין לפחות את packageName
של אפליקציית היעד, את metrics
שרוצים למדוד וכמה iterations
צריך להריץ את ההשוואה לשוק.
Kotlin
@LargeTest @RunWith(AndroidJUnit4::class) class SampleStartupBenchmark { @get:Rule val benchmarkRule = MacrobenchmarkRule() @Test fun startup() = benchmarkRule.measureRepeated( packageName = TARGET_PACKAGE, metrics = listOf(StartupTimingMetric()), iterations = DEFAULT_ITERATIONS, setupBlock = { // Press home button before each run to ensure the starting activity isn't visible. pressHome() } ) { // starts default launch activity startActivityAndWait() } }
Java
@LargeTest @RunWith(AndroidJUnit4.class) public class SampleStartupBenchmark { @Rule public MacrobenchmarkRule benchmarkRule = new MacrobenchmarkRule(); @Test public void startup() { benchmarkRule.measureRepeated( /* packageName */ TARGET_PACKAGE, /* metrics */ Arrays.asList(new StartupTimingMetric()), /* iterations */ 5, /* measureBlock */ scope -> { // starts default launch activity scope.startActivityAndWait(); return Unit.INSTANCE; } ); } }
בקטע התאמה אישית של נקודות ההשוואה מוסבר על כל האפשרויות להתאמה אישית של נקודת ההשוואה.
הפעלת ההשוואה לשוק
מריצים את הבדיקה מתוך Android Studio כדי למדוד את הביצועים של האפליקציה במכשיר. אפשר להריץ את המדדים להשוואה כמו שמריצים כל @Test
אחר באמצעות הפעולה בסרגל הצד שליד מחלקת הבדיקה או המתודה, כמו שמוצג באיור 5.
איור 5. מריצים את Macrobenchmark באמצעות פעולת השוליים לצד מחלקת הבדיקה.
אפשר גם להריץ את כל בדיקות ההשוואה במודול Gradle משורת הפקודה באמצעות הפקודה connectedCheck
:
./gradlew :macrobenchmark:connectedCheck
כדי להריץ בדיקה אחת, מריצים את הפקודה הבאה:
./gradlew :macrobenchmark:connectedCheck -P android.testInstrumentationRunnerArguments.class=com.example.macrobenchmark.startup.SampleStartupBenchmark#startup
במאמר השוואה ב-Continuous Integration מוסבר איך להריץ ולעקוב אחרי נקודות השוואה ב-Continuous Integration.
תוצאות ההשוואה לשוק
אחרי הפעלת בדיקת ביצועים מוצלחת, המדדים מוצגים ישירות ב-Android Studio ומופקים לשימוש ב-CI בקובץ JSON. כל איטרציה שנמדדת מתעדת מעקב נפרד של המערכת. כדי לפתוח את תוצאות ה-trace, לוחצים על הקישורים בחלונית Test Results, כמו שמוצג באיור 6:
איור 6. תוצאות של השוואה להפעלה.
כשהנתונים נטענים, מוצגת ב-Android Studio בקשה לבחור את התהליך שרוצים לנתח. הבחירה מאוכלסת מראש בתהליך של אפליקציית היעד, כפי שמוצג באיור 7:
איור 7. בחירת תהליך מעקב ב-Studio.
אחרי שהקובץ של ה-trace נטען, התוצאות מוצגות ב-Studio בכלי CPU profiler:
איור 8. תיעוד עקבות המערכת.
דוחות JSON וכל עקבות התיעוד מועתקים אוטומטית מהמכשיר למארח. הן נכתבות במכונת המארח במיקום הבא:
project_root/module/build/outputs/connected_android_test_additional_output/debugAndroidTest/connected/device_id/
גישה ידנית לקבצים של פרטי ההעברה
אם רוצים להשתמש בכלי Perfetto כדי לנתח קובץ מעקב, צריך לבצע שלבים נוספים. בעזרת Perfetto אפשר לבדוק את כל התהליכים שמתרחשים במכשיר במהלך המעקב, בעוד שפרופיל המעבד (CPU) של Android Studio מגביל את הבדיקה לתהליך יחיד.
אם מפעילים את הבדיקות מ-Android Studio או משורת הפקודה של Gradle, קובצי המעקב מועתקים אוטומטית מהמכשיר למארח. הם נכתבים במכונת המארח במיקום הבא:
project_root/module/build/outputs/connected_android_test_additional_output/debugAndroidTest/connected/device_id/TrivialStartupBenchmark_startup[mode=COLD]_iter002.perfetto-trace
אחרי שקובץ העקבות נמצא במערכת המארחת, אפשר לפתוח אותו ב-Android Studio באמצעות File > Open בתפריט. כאן מוצגת תצוגת הכלי לניתוח הביצועים שמופיעה בקטע הקודם.
שגיאות בהגדרות
אם האפליקציה לא מוגדרת בצורה נכונה – כלומר, אפשר לבצע בה ניפוי באגים או שלא ניתן ליצור ממנה פרופיל – הפונקציה Macrobenchmark מחזירה שגיאה במקום לדווח על מדידה שגויה או לא מלאה. אפשר להשבית את השגיאות האלה באמצעות הארגומנט androidx.benchmark.suppressErrors
.
בנוסף, Macrobenchmark מחזירה שגיאות כשמנסים למדוד אמולטור או מכשיר עם סוללה חלשה, כי זה עלול לפגוע בזמינות הליבה ובמהירות השעון.
התאמה אישית של נקודות ההשוואה
הפונקציה measureRepeated
מקבלת פרמטרים שונים שמשפיעים על המדדים שהספרייה אוספת, על אופן ההפעלה והקומפילציה של האפליקציה או על מספר האיטרציות של נקודת ההשוואה.
תיעוד המדדים
מדדים הם סוג המידע העיקרי שמופק מהשוואות לשוק. המדדים הבאים זמינים:
מידע נוסף על מדדים זמין במאמר איך לוכדים מדדי מאקרו-בנצ'מרק.
שיפור נתוני המעקב באמצעות אירועים מותאמים אישית
כדאי להטמיע באפליקציה אירועי מעקב מותאמים אישית, שמוצגים עם שאר דוח המעקב ויכולים לעזור לזהות בעיות שספציפיות לאפליקציה. מידע נוסף על יצירת אירועי מעקב מותאמים אישית זמין במאמר הגדרת אירועים מותאמים אישית.
CompilationMode
בבדיקות ביצועים רחבות היקף אפשר לציין CompilationMode
, שמגדיר כמה מהאפליקציה צריך לעבור קומפילציה מראש מקוד בייט של DEX (פורמט קוד הבייט ב-APK) לקוד מכונה (בדומה לקומפילציה מראש של C++).
כברירת מחדל, בדיקות Macrobenchmark מופעלות עם CompilationMode.DEFAULT
, שמתקין פרופיל בסיסי – אם הוא זמין – ב-Android 7 (רמת API 24) ואילך.
אם אתם משתמשים ב-Android 6 (רמת API 23) או בגרסאות קודמות, מצב הקומפילציה מבצע קומפילציה מלאה של ה-APK כהתנהגות ברירת מחדל של המערכת.
אפשר להתקין פרופיל בסיסי אם אפליקציית היעד מכילה גם פרופיל בסיסי וגם את ספריית ProfileInstaller
.
ב-Android 7 ואילך, אפשר להתאים אישית את CompilationMode
כדי להשפיע על כמות ההידור המוקדם במכשיר, וכך לדמות רמות שונות של הידור מוקדם (AOT) או שמירת נתונים במטמון של JIT. כדאי לצפות בסרטונים של CompilationMode.Full
, CompilationMode.Partial
, CompilationMode.None
וCompilationMode.Ignore
.
התכונה הזו מבוססת על פקודות קומפילציה של ART. כל בדיקת ביצועים מוחקת את נתוני הפרופיל לפני שהיא מתחילה, כדי למנוע הפרעות בין בדיקות הביצועים.
StartupMode
כדי לבצע הפעלה של פעילות, אפשר להעביר מצב הפעלה מוגדר מראש:
COLD
, WARM
או HOT
. הפרמטר הזה משנה את אופן ההפעלה של הפעילות ואת מצב התהליך בתחילת הבדיקה.
מידע נוסף על סוגי ההפעלה זמין במאמר זמן ההפעלה של האפליקציה.
טעימות
פרויקט לדוגמה זמין בMacrobenchmark Sample במאגר ב-GitHub.
שליחת משוב
כדי לדווח על בעיות או לשלוח בקשות לתכונות ב-Jetpack Macrobenchmark, אפשר להיכנס אל הכלי הציבורי למעקב אחר בעיות.
מומלץ
- הערה: טקסט הקישור מוצג כש-JavaScript מושבת
- איסוף מדדים של השוואה
- יצירת פרופיל Baseline {:#creating-profile-rules}
- אוטומציה של מדידה באמצעות ספריית ההשוואה {:#measuring-optimization}