برای آشنایی با نحوه استفاده از کتابخانه Microbenchmark با افزودن تغییرات به کد برنامه، به بخش شروع سریع مراجعه کنید. برای آشنایی با نحوه تکمیل راهاندازی کامل با تغییرات پیچیدهتر در پایگاه کد، به بخش راهاندازی کامل پروژه مراجعه کنید.
راهاندازی سریع
این بخش نشان میدهد که چگونه میتوانید محکزنی را امتحان کنید و اندازهگیریهای یکباره را اجرا کنید بدون اینکه نیاز باشد کد را به پیمانهها منتقل کنید. برای نتایج عملکرد دقیق، این مراحل شامل غیرفعال کردن اشکالزدایی در برنامه شما میشود، بنابراین این را در یک نسخه کاری محلی نگه دارید بدون اینکه تغییرات را به سیستم کنترل منبع خود اعمال کنید.
برای انجام محکزنی یکباره، کارهای زیر را انجام دهید:
کتابخانه را به فایل
build.gradleیاbuild.gradle.ktsواحدتان اضافه کنید:کاتلین
dependencies { implementation("androidx.benchmark:benchmark-junit4:1.2.4") }
شیک
dependencies { implementation 'androidx.benchmark:benchmark-junit4:1.2.4' }
بهجای وابستگی
androidTestImplementation، از وابستگیimplementationاستفاده کنید. اگر ازandroidTestImplementationاستفاده کنید، محکها اجرا نمیشوند زیرا مانیفست کتابخانه در مانیفست برنامه ادغام نشده است.نوع ساخت
debugرا بهروز کنید تا قابلاشکالزدایی نباشد:کاتلین
android { ... buildTypes { debug { isDebuggable = false } } }
شیک
android { ... buildTypes { debug { debuggable false } } }
تغییر دادن
testInstrumentationRunnerبهAndroidBenchmarkRunner:کاتلین
android { ... defaultConfig { testInstrumentationRunner = "androidx.benchmark.junit4.AndroidBenchmarkRunner" } }
شیک
android { ... defaultConfig { testInstrumentationRunner "androidx.benchmark.junit4.AndroidBenchmarkRunner" } }
برای افزودن محک، نمونهای از
BenchmarkRuleرا در فایل آزمایشی در دایرکتوریandroidTestاضافه کنید. برای اطلاعات بیشتر درباره نوشتن محکها، به ایجاد کلاس Microbenchmark مراجعه کنید.تکهکد زیر نحوه افزودن محک به آزمایش Instrumented را نشان میدهد:
کاتلین
@RunWith(AndroidJUnit4::class) class SampleBenchmark { @get:Rule val benchmarkRule = BenchmarkRule() @Test fun benchmarkSomeWork() { benchmarkRule.measureRepeated { doSomeWork() } } }
جاوا
@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 جداگانه قرار دهید و وابستگی به آن واحد را همانطور که در شکل ۱ نشان داده شده است تنظیم کنید.
:app،
:microbenchmark، و :benchmarkable،
که به Microbenchmarks اجازه میدهد کد را در واحد :benchmarkable
محکزنی کند.برای افزودن یک ماژول Gradle جدید، میتوانید از دستیار ماژول در Android Studio استفاده کنید. جادوگر
ماژولی ایجاد میکند که برای محکزنی ازپیش پیکربندی شده است،
و فهرست راهنمای محکزنی به آن اضافه شده و debuggable روی false تنظیم شده است.
روی پروژه یا واحدتان در پانل پروژه در Android Studio کلیک راست کنید و روی جدید > واحد کلیک کنید.
معیار را در قاب الگوها انتخاب کنید.
Microbenchmark را بهعنوان نوع پیمانه محک انتخاب کنید.
برای نام پیمانه، «microbenchmark» را تایپ کنید.
روی پایان کلیک کنید.
پساز ایجاد ماژول، فایل build.gradle یا build.gradle.kts آن را تغییر دهید و androidTestImplementation را به ماژول حاوی کد برای محکزنی اضافه کنید:
کاتلین
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 استفاده کنید.
کد زیر نمونهای از محک را نشان میدهد:
کاتلین
@RunWith(AndroidJUnit4::class) class SampleBenchmark { @get:Rule val benchmarkRule = BenchmarkRule() @Test fun benchmarkSomeWork() { benchmarkRule.measureRepeated { doSomeWork() } } }
جاوا
@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{} اندازهگیری شود غیرفعال کنید. این بخشها معمولاً نشاندهنده کدی هستند که باید در هر تکرار محک اجرا کنید.
کاتلین
// 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) }
جاوا
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 دیگری بااستفاده از
کنش حاشیه کنار کلاس یا روش آزمایشی خود اجرا کنید، همانطور که در شکل ۳ نشان داده شده است.
یا از خط فرمان، 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 قرار دارد.
خطاهای پیکربندی
این کتابخانه شرایط زیر را شناسایی میکند تا مطمئن شود پروژه و محیط شما برای عملکرد دقیق در نسخه نهایی راهاندازی شده است:
- «قابلاشکالزدایی» روی
falseتنظیم شده است. - از دستگاه فیزیکی استفاده میشود—شبیهسازها پشتیبانی نمیشوند.
- اگر دستگاه ریشهیابی شده باشد، ساعتها قفل میشوند.
- میزان شارژ باتری دستگاه حداقل ۲۵٪ باشد.
اگر هریک از بررسیهای قبلی ناموفق باشد، محک خطا گزارش میکند تا از اندازهگیریهای نادرست جلوگیری شود.
برای سرکوب کردن انواع خاص خطا بهعنوان هشدار و جلوگیری از توقف محک، نوع خطا را در فهرستی جداشده با کاما به آرگومان ابزار دقیق androidx.benchmark.suppressErrors ارسال کنید.
میتوانید این را از اسکریپت Gradle خود تنظیم کنید، همانطور که در مثال زیر نشان داده شده است:
کاتلین
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_ پیشافزایی میکند.
توصیهشده برای شما
- توجه: وقتی جاوا اسکریپت خاموش باشد، نوشتار پیوند نمایش داده میشود
- نوشتن Macrobenchmark
- ساختن Microbenchmarks بدون Gradle
- ایجاد «نمایههای مبنا» {:#creating-profile-rules}