בקטע מדריך למתחילים מוסבר איך להשתמש בספריית Microbenchmark על ידי הוספת שינויים לקוד האפליקציה. בקטע הגדרה מלאה של הפרויקט מוסבר איך להשלים הגדרה מלאה עם שינויים מורכבים יותר בקוד.
מדריך למתחילים
בקטע הזה נסביר איך לנסות את מדדי הביצועים ולהריץ מדידות חד-פעמיות בלי להעביר קוד למודולים. כדי לקבל תוצאות מדויקות של ביצועים, השלבים האלה כוללים השבתה של ניפוי באגים באפליקציה, לכן צריך לשמור את זה בעותק עבודה מקומי בלי להתחייב לשינויים במערכת בקרת הגרסאות.
כדי לבצע בדיקת ביצועים חד-פעמית:
מוסיפים את הספרייה לקובץ
build.gradle
אוbuild.gradle.kts
של המודול:Kotlin
dependencies { implementation("androidx.benchmark:benchmark-junit4:1.2.4") }
Groovy
dependencies { implementation 'androidx.benchmark:benchmark-junit4:1.2.4' }
משתמשים ביחס תלות מסוג
implementation
במקום ביחס תלות מסוגandroidTestImplementation
. אם משתמשים ב-androidTestImplementation
, לא ניתן להריץ את אמות המידה כי המניפסט של הספרייה לא משולב במניפסט של האפליקציה.מעדכנים את סוג ה-build של
debug
כך שלא ניתן יהיה לנפות באגים בו:Kotlin
android { ... buildTypes { debug { isDebuggable = false } } }
Groovy
android { ... buildTypes { debug { debuggable false } } }
משנים את הערך של
testInstrumentationRunner
ל-AndroidBenchmarkRunner
:Kotlin
android { ... defaultConfig { testInstrumentationRunner = "androidx.benchmark.junit4.AndroidBenchmarkRunner" } }
Groovy
android { ... defaultConfig { testInstrumentationRunner "androidx.benchmark.junit4.AndroidBenchmarkRunner" } }
מוסיפים מופע של
BenchmarkRule
בקובץ בדיקה בספרייהandroidTest
כדי להוסיף את מדד הביצועים. מידע נוסף על כתיבת מדדי ביצועים זמין במאמר יצירת כיתה של מדדי ביצועים מיקרו.בקטע הקוד הבא מוצג איך מוסיפים בדיקת ביצועים למבחן עם כלי למדידת ביצועים:
Kotlin
@RunWith(AndroidJUnit4::class) class SampleBenchmark { @get:Rule val benchmarkRule = BenchmarkRule() @Test fun benchmarkSomeWork() { benchmarkRule.measureRepeated { doSomeWork() } } }
Java
@RunWith(AndroidJUnit4.class) class SampleBenchmark { @Rule public BenchmarkRule benchmarkRule = new BenchmarkRule(); @Test public void benchmarkSomeWork() { BenchmarkRuleKt.measureRepeated( (Function1<BenchmarkRule.Scope, Unit>) scope -> doSomeWork() ); } } }
כדי ללמוד איך לכתוב בדיקת ביצועים, אפשר לדלג לקטע יצירת כיתה של בדיקת ביצועים ברמת המיקרו.
הגדרה מלאה של הפרויקט
כדי להגדיר בדיקות ביצועים שוטפות במקום בדיקות חד-פעמיות, צריך להפריד את בדיקות הביצועים למודול משלהם. כך אפשר להבטיח שההגדרות שלהם, כמו הגדרת debuggable
ל-false
, יהיו נפרדות מהבדיקות הרגילות.
מכיוון ש-Microbenchmark מפעיל את הקוד ישירות, צריך להציב את הקוד שרוצים למדוד במודול נפרד ב-Gradle ולהגדיר את התלות באותו מודול, כפי שמוצג באיור 1.
כדי להוסיף מודול Gradle חדש, אפשר להשתמש באשף המודול ב-Android Studio. האשף יוצר מודול שמוגדר מראש לבדיקת ביצועים, עם הוספה של ספריית ביצועים והגדרה של debuggable
כ-false
.
לוחצים לחיצה ימנית על הפרויקט או המודול בחלונית Project ב-Android Studio, ואז לוחצים על New > Module.
בוחרים באפשרות Benchmark בחלונית Templates.
בוחרים באפשרות Microbenchmark כסוג המודול של מדד הביצועים.
מקלידים microbenchmark בשם המודול.
לוחצים על סיום.
אחרי שיוצרים את המודול, משנים את הקובץ build.gradle
או build.gradle.kts
שלו ומוסיפים את androidTestImplementation
למודול שמכיל את הקוד ליצירת נקודת השוואה:
Kotlin
dependencies { // The module name might be different. androidTestImplementation(project(":benchmarkable")) }
Groovy
dependencies { // The module name might be different. androidTestImplementation project(':benchmarkable') }
יצירת כיתה של Microbenchmark
מדדי ביצועים הם בדיקות סטנדרטיות של אינסטרומנטציה. כדי ליצור מדד ביצועים, משתמשים בכיתה BenchmarkRule
שסופקת על ידי הספרייה. כדי ליצור נכסי benchmark לפעילויות, משתמשים ב-ActivityScenario
או ב-ActivityScenarioRule
. כדי לבצע בדיקת ביצועים של קוד ממשק משתמש, משתמשים ב-@UiThreadTest
.
הקוד הבא מציג מדד ביצועים לדוגמה:
Kotlin
@RunWith(AndroidJUnit4::class) class SampleBenchmark { @get:Rule val benchmarkRule = BenchmarkRule() @Test fun benchmarkSomeWork() { benchmarkRule.measureRepeated { doSomeWork() } } }
Java
@RunWith(AndroidJUnit4.class) class SampleBenchmark { @Rule public BenchmarkRule benchmarkRule = new BenchmarkRule(); @Test public void benchmarkSomeWork() { final BenchmarkState state = benchmarkRule.getState(); while (state.keepRunning()) { doSomeWork(); } } }
השבתת התזמון להגדרה
אפשר להשבית את התזמון של קטעי קוד שאתם לא רוצים למדוד באמצעות הבלוק runWithTimingDisabled{}
. בדרך כלל, הקטעים האלה מייצגים קוד שצריך להריץ בכל חזרה של מדד הביצועים.
Kotlin
// using random with the same seed, so that it generates the same data every run private val random = Random(0) // create the array once and just copy it in benchmarks private val unsorted = IntArray(10_000) { random.nextInt() } @Test fun benchmark_quickSort() { // ... benchmarkRule.measureRepeated { // copy the array with timing disabled to measure only the algorithm itself listToSort = runWithTimingDisabled { unsorted.copyOf() } // sort the array in place and measure how long it takes SortingAlgorithms.quickSort(listToSort) } // assert only once not to add overhead to the benchmarks assertTrue(listToSort.isSorted) }
Java
private final int[] unsorted = new int[10000]; public SampleBenchmark() { // Use random with the same seed, so that it generates the same data every // run. Random random = new Random(0); // Create the array once and copy it in benchmarks. Arrays.setAll(unsorted, (index) -> random.nextInt()); } @Test public void benchmark_quickSort() { final BenchmarkState state = benchmarkRule.getState(); int[] listToSort = new int[0]; while (state.keepRunning()) { // Copy the array with timing disabled to measure only the algorithm // itself. state.pauseTiming(); listToSort = Arrays.copyOf(unsorted, 10000); state.resumeTiming(); // Sort the array in place and measure how long it takes. SortingAlgorithms.quickSort(listToSort); } // Assert only once, not to add overhead to the benchmarks. assertTrue(SortingAlgorithmsKt.isSorted(listToSort)); }
כדאי לצמצם את כמות העבודה שבוצעה בתוך הבלוק measureRepeated
ובתוך runWithTimingDisabled
. הבלוק measureRepeated
מופעל כמה פעמים, והוא יכול להשפיע על משך הזמן הכולל הנדרש להרצת מדד הביצועים. אם אתם צריכים לאמת תוצאות מסוימות של מדד ביצועים, תוכלו לאמת את התוצאה האחרונה במקום לעשות זאת בכל חזרה של מדד הביצועים.
הרצת נקודת ההשוואה
ב-Android Studio, מריצים את מדד הביצועים כמו כל @Test
באמצעות הפעולה בפס ההנחה לצד הכיתה או השיטה של הבדיקה, כפי שמוצג באיור 3.
לחלופין, אפשר להריץ את הפקודה connectedCheck
משורת הפקודה כדי להריץ את כל הבדיקות מהמודול שצוין ב-Gradle:
./gradlew benchmark:connectedCheck
או בדיקה אחת:
./gradlew benchmark:connectedCheck -P android.testInstrumentationRunnerArguments.class=com.example.benchmark.SampleBenchmark#benchmarkSomeWork
תוצאות של בנצ'מרק
אחרי הרצת Microbenchmark מוצלחת, המדדים מוצגים ישירות ב-Android Studio, ודוח מלא של מדדי ביצועים עם מדדים נוספים ומידע על המכשיר זמין בפורמט JSON.
גם דוחות JSON וכל עקבות של יצירת פרופילים מועתקים באופן אוטומטי מהמכשיר למארח. הם נכתבים במכונה המארחת במיקום הבא:
project_root/module/build/outputs/connected_android_test_additional_output/debugAndroidTest/connected/device_id/
כברירת מחדל, דוח ה-JSON נכתב בדיסק במכשיר בתיקיית המדיה המשותפת החיצונית של קובץ ה-APK לבדיקה, שנמצאת בדרך כלל ב-/storage/emulated/0/Android/media/**app_id**/**app_id**-benchmarkData.json
.
שגיאות בהגדרות
הספרייה מזהה את התנאים הבאים כדי לוודא שהפרויקט והסביבה מוגדרים לביצועים מדויקים כמו בגרסת המהדורה:
- הערך של Debuggable מוגדר כ-
false
. - נעשה שימוש במכשיר פיזי – אין תמיכה באמולטורים.
- השעונים ננעלים אם המכשיר עבר תהליך רוט (Root).
- רמת הטעינה של הסוללה במכשיר צריכה להיות לפחות 25%.
אם אחת מהבדיקות הקודמות נכשלת, מדד הביצועים מדווח על שגיאה כדי למנוע מדידות לא מדויקות.
כדי למנוע את הצגת סוגי שגיאות ספציפיים כאזהרות וכדי למנוע מהן לעצור את בדיקת הביצועים, מעבירים את סוג השגיאה ברשימה מופרדת בפסיקים לארגומנט של המדידה androidx.benchmark.suppressErrors
.
אפשר להגדיר את זה בסקריפט של Gradle, כמו בדוגמה הבאה:
Kotlin
android { defaultConfig { … testInstrumentationRunnerArguments["androidx.benchmark.suppressErrors"] = "DEBUGGABLE,LOW-BATTERY" } }
Groovy
android { defaultConfig { … testInstrumentationRunnerArguments["androidx.benchmark.suppressErrors"] = "DEBUGGABLE,LOW-BATTERY" } }
אפשר גם לדכא שגיאות משורת הפקודה:
$ ./gradlew :benchmark:connectedCheck -P andoidtestInstrumentationRunnerArguments.androidx.benchmark.supperssErrors=DEBUGGABLE,LOW-BATTERY
דיכוי השגיאות מאפשר להריץ את מדד הביצועים במצב שהוגדר באופן שגוי, והשם של הפלט של מדד הביצועים משתנה בכוונה על ידי הוספת השגיאה לשמות הבדיקות. לדוגמה, כשמריצים בדיקת ביצועים שניתן לנפות בה באגים עם ההשתקה בקטע הקוד הקודם, שמות הבדיקות מתחילים ב-DEBUGGABLE_
.
מומלץ עבורך
- הערה: טקסט הקישור מוצג כש-JavaScript מושבת
- כתיבה של Macrobenchmark
- יצירת מדדי Microbenchmark בלי Gradle
- יצירת פרופילי Baseline {:#creating-profile-rules}