כדי ללמוד איך להשתמש בספריית Microbenchmark על ידי הוספת שינויים לקוד האפליקציה, עיינו בקטע התחלה מהירה. כדי ללמוד איך להשלים הגדרה מלאה עם שינויים מורכבים יותר בבסיס הקוד, עיינו בקטע הגדרת פרויקט מלאה.
מדריך למתחילים
בקטע הזה מוסבר איך לנסות את ההשוואה לשוק ולהריץ מדידות חד-פעמיות בלי להעביר את הקוד למודולים. כדי לקבל תוצאות מדויקות, השלבים האלה כוללים השבתה של ניפוי הבאגים באפליקציה. לכן, חשוב לשמור את זה בעותק מקומי בלי להחיל את השינויים במערכת בקרת המקור.
כדי לבצע השוואה חד-פעמית:
מוסיפים את הספרייה לקובץ
build.gradleאוbuild.gradle.ktsשל המודול:Kotlin
dependencies { implementation("androidx.benchmark:benchmark-junit4:1.2.4") }
מגניב
dependencies { implementation 'androidx.benchmark:benchmark-junit4:1.2.4' }
משתמשים ביחסי תלות מסוג
implementationבמקום ביחסי תלות מסוגandroidTestImplementation. אם משתמשים ב-androidTestImplementation, בדיקות הביצועים לא פועלות כי המניפסט של הספרייה לא מוזג עם המניפסט של האפליקציה.מעדכנים את סוג ה-build של
debugכך שלא ניתן יהיה לבצע בו ניפוי באגים:Kotlin
android { ... buildTypes { debug { isDebuggable = false } } }
מגניב
android { ... buildTypes { debug { debuggable false } } }
משנים את הערך של
testInstrumentationRunnerל-AndroidBenchmarkRunner:Kotlin
android { ... defaultConfig { testInstrumentationRunner = "androidx.benchmark.junit4.AndroidBenchmarkRunner" } }
מגניב
android { ... defaultConfig { testInstrumentationRunner "androidx.benchmark.junit4.AndroidBenchmarkRunner" } }
כדי להוסיף את נקודת ההשוואה, מוסיפים מופע של
BenchmarkRuleבקובץ בדיקה בספרייהandroidTest. מידע נוסף על כתיבת נקודות השוואה זמין במאמר יצירת מחלקה של Microbenchmark.בקטע הקוד הבא מוצג איך להוסיף נקודת השוואה לבדיקה עם מכשור:
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() ); } } }
כדי ללמוד איך לכתוב בדיקת השוואה לשוק, דלגו לקטע יצירת מחלקה של Microbenchmark.
הגדרה מלאה של הפרויקט
כדי להגדיר בדיקת ביצועים קבועה ולא חד-פעמית, צריך לבודד את בדיקות הביצועים למודול משלהן. כך אפשר לוודא שההגדרות שלהם, כמו הגדרת debuggable ל-false, נפרדות מהבדיקות הרגילות.
מכיוון ש-Microbenchmark מריץ את הקוד ישירות, צריך להציב את הקוד שרוצים לבדוק במודול Gradle נפרד ולהגדיר תלות במודול הזה, כמו שמוצג באיור 1.
:app, :microbenchmark ו-:benchmarkable, שמאפשרים ל-Microbenchmarks לבצע השוואת ביצועים של קוד במודול :benchmarkable.כדי להוסיף מודול Gradle חדש, אתם יכולים להשתמש באשף המודולים ב-Android Studio. האשף יוצר מודול שמוגדר מראש להשוואה, עם ספריית השוואה שנוספה ו-debuggable מוגדר ל-false.
לוחצים לחיצה ימנית על הפרויקט או המודול בחלונית Project ב-Android Studio ולוחצים על New > Module.
בחלונית תבניות, בוחרים באפשרות השוואה לשוק.
בוחרים באפשרות Microbenchmark בתור סוג המודול של נקודת ההשוואה.
מקלידים "microbenchmark" בשם המודול.
לוחצים על סיום.
אחרי שיוצרים את המודול, משנים את הקובץ build.gradle או build.gradle.kts שלו ומוסיפים את androidTestImplementation למודול שמכיל את הקוד שרוצים לבדוק:
Kotlin
dependencies { // The module name might be different. androidTestImplementation(project(":benchmarkable")) }
מגניב
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. - אתם משתמשים במכשיר פיזי – אין תמיכה באמולטורים.
- השעונים נעולים אם המכשיר עבר רוט.
- רמת הטעינה של הסוללה במכשיר היא לפחות 25%.
אם אחת מהבדיקות הקודמות נכשלת, מבחן הביצועים מדווח על שגיאה כדי למנוע מדידות לא מדויקות.
כדי להסתיר סוגי שגיאות ספציפיים כאזהרות ולמנוע מהם לעצור את הבדיקה, מעבירים את סוג השגיאה ברשימה מופרדת בפסיקים לארגומנט האינסטרומנטציה androidx.benchmark.suppressErrors.
אפשר להגדיר את זה בסקריפט של Gradle, כמו בדוגמה הבאה:
Kotlin
android { defaultConfig { … testInstrumentationRunnerArguments["androidx.benchmark.suppressErrors"] = "DEBUGGABLE,LOW-BATTERY" } }
מגניב
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}