כדי ללמוד איך להשתמש בספריית ה-Microbenchmark על ידי הוספת שינויים את הקוד של האפליקציה, ראו מדריך למתחילים. כדי ללמוד איך להשלים הגדרה מלאה ולבצע שינויים מורכבים יותר ב-codebase שלכם. תוכלו לראות את קטע בנושא הגדרת פרויקט מלאה.
מדריך למתחילים
בקטע הזה מוסבר איך לנסות נקודת השוואה ולהריץ מדידות חד-פעמיות בלי שתצטרכו להעביר קוד למודולים. כדי לקבל תוצאות מדויקות של ביצועים, שלבים אלה כוללים השבתת ניפוי באגים באפליקציה, לכן יש להשאיר את הפעולה הזו עותק פעיל בלי לשמור את השינויים במערכת בקרת המקורות.
כדי לבצע השוואה חד-פעמית:
מוסיפים את הספרייה לקובץ
build.gradle
אוbuild.gradle.kts
של המודול:Kotlin
dependencies { implementation("androidx.benchmark:benchmark-junit4:1.2.3") }
מגניב
dependencies { implementation 'androidx.benchmark:benchmark-junit4:1.2.3' }
צריך להשתמש בתלות של
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() ); } } }
כדי ללמוד איך כותבים נקודת השוואה, אפשר לדלג אל יצירת כיתה של Microbench.
הגדרת הפרויקט המלא
כדי להגדיר השוואה לשוק רגיל במקום השוואה חד פעמית, צריך לבודד
במודול שלהם. זה עוזר להבטיח שההגדרות שלהם
כמו הגדרת הערך debuggable
כ-false
, היא בנפרד מבדיקות רגילות.
מאחר שמערכת Microbenchmark מריצה את הקוד שלך ישירות, עליך למקם את הקוד הרצוי בנצ'מרק למודול Gradle נפרד, ולהגדיר את התלות במודול הזה בתור שמוצגת באיור 1.
![מבנה האפליקציה](https://developer.android.com/static/topic/performance/images/benchmark_images/microbenchmark_modules.png?authuser=9&hl=he)
:app
,
:microbenchmark
ו-:benchmarkable
Gradle
, שמאפשר ל-Microbenchmarks
מודול :benchmarkable
.כדי להוסיף מודול Gradle חדש, תוכלו להשתמש באשף המודולים ב-Android Studio.
יוצר מודול שמוגדר מראש להשוואה, עם
ספריית ההשוואה לשוק נוספה והערך debuggable
הוגדר לערך false
.
ב-Android, לוחצים לחיצה ימנית על הפרויקט או על המודול פרויקט. Studio ולוחצים על חדש > יחידת לימוד.
בוחרים את האפשרות השוואה לשוק בחלונית תבניות.
בוחרים באפשרות Microbenchmark בתור סוג המודול של ההשוואה לשוק.
מקלידים 'microbenchmark' לשם המודול.
לוחצים על סיום.
![הגדרת מודול ספרייה חדש](https://developer.android.com/static/topic/performance/images/benchmark_images/microbenchmark_module_giraffe.png?authuser=9&hl=he)
לאחר יצירת המודול, משנים את 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.
![הפעלת Microbench](https://developer.android.com/static/topic/performance/images/benchmark_images/microbenchmark_run.png?authuser=9&hl=he)
לחלופין, משורת הפקודה, מריצים את הפקודה connectedCheck
כדי להריץ את
של הבדיקות ממודול Gradle שצוין:
./gradlew benchmark:connectedCheck
או בדיקה אחת:
./gradlew benchmark:connectedCheck -P android.testInstrumentationRunnerArguments.class=com.example.benchmark.SampleBenchmark#benchmarkSomeWork
תוצאות ההשוואה לשוק
לאחר הרצה מוצלחת של Microbenchmark, המדדים מוצגים ישירות ב-Android Studio ודוח השוואה מלא של ההשוואה לשוק עם מדדים נוספים ומכשירים נוספים זמין בפורמט JSON.
![תוצאות המיקרובנצ'מרק](https://developer.android.com/static/topic/performance/images/benchmark_images/microbenchmark_results.png?authuser=9&hl=he)
גם דוחות 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
שגיאות הגדרה
הספרייה מזהה את התנאים הבאים כדי להבטיח שהפרויקט מוגדרים לביצועים מדויקים ברמת ההשקה:
- האפשרות 'ניפוי באגים' מוגדרת ל
false
. - נעשה שימוש במכשיר פיזי. אין תמיכה באמולטורים.
- השעונים נעולים אם המכשיר עבר תהליך רוט (Root).
- רמת טעינה מספקת של הסוללה במכשיר של 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 מושבת
- כתיבה של נקודת מאקרו בנצ'מרק
- בניית נקודות מיקרובנצ'מרקים ללא Gradle
- יצירת פרופילים בסיסיים {:#create-profile-כללים}