בקטע מדריך למתחילים מוסבר איך להשתמש בספריית Microbenchmark על ידי הוספת שינויים לקוד האפליקציה. בקטע Full project setup (הגדרת הפרויקט המלא) מוסבר איך לבצע הגדרה מלאה, כולל שינויים מורכבים יותר ב-codebase.
מדריך למתחילים
בקטע הזה נסביר איך להשתמש בבנצ'מרק ולהריץ מדידות חד-פעמיות בלי להעביר קוד למודולים. כדי לקבל תוצאות מדויקות של ביצועים, השלבים האלה כוללים השבתה של ניפוי באגים באפליקציה, לכן צריך לשמור את זה בעותק עבודה מקומי בלי להתחייב לשינויים במערכת בקרת הגרסאות.
כדי לבצע השוואה חד-פעמית:
מוסיפים את הספרייה לקובץ
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() ); } } }
במאמר יצירת כיתה ב-Microbench מוסבר איך כותבים נקודת השוואה.
הגדרה מלאה של הפרויקט
כדי להגדיר בדיקות ביצועים שוטפות במקום בדיקות חד-פעמיות, צריך להפריד את בדיקות הביצועים למודול משלהם. כך תוכלו לוודא שההגדרות שלהם, כמו הגדרת 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
שסופקה בספרייה. כדי ליצור נקודות השוואה לפעילויות, משתמשים ב-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
- יצירת פרופילים בסיסיים {:#creating-profile-rules}