یک Microbenchmark بنویسید

برای یادگیری نحوه استفاده از کتابخانه Microbenchmark با اضافه کردن تغییرات به کد برنامه خود، به بخش شروع سریع مراجعه کنید. برای یادگیری نحوه تکمیل یک راه‌اندازی کامل با تغییرات پیچیده‌تر در پایگاه کد خود، به بخش راه‌اندازی کامل پروژه مراجعه کنید.

شروع سریع

این بخش نحوه‌ی امتحان کردن بنچمارک و اجرای اندازه‌گیری‌های یک‌باره را بدون نیاز به انتقال کد به ماژول‌ها نشان می‌دهد. برای نتایج دقیق عملکرد، این مراحل شامل غیرفعال کردن اشکال‌زدایی در برنامه‌ی شما می‌شود، بنابراین این را در یک کپی کاری محلی نگه دارید بدون اینکه تغییرات را در سیستم کنترل منبع خود اعمال کنید.

برای انجام بنچمارک تک مرحله‌ای، موارد زیر را انجام دهید:

  1. کتابخانه را به فایل 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 استفاده کنید، بنچمارک‌ها اجرا نمی‌شوند زیرا manifest کتابخانه در manifest برنامه ادغام نشده است.

  2. نوع ساخت debug را به‌روزرسانی کنید تا قابل اشکال‌زدایی نباشد:

    کاتلین

    android {
        ...
        buildTypes {
            debug {
                isDebuggable = false
            }
        }
    }

    گرووی

    android {
        ...
        buildTypes {
            debug {
                debuggable false
            }
        }
    }
  3. testInstrumentationRunner را به AndroidBenchmarkRunner تغییر دهید:

    کاتلین

    android {
        ...
        defaultConfig {
            testInstrumentationRunner = "androidx.benchmark.junit4.AndroidBenchmarkRunner"
        }
    }

    گرووی

    android {
        ...
        defaultConfig {
            testInstrumentationRunner "androidx.benchmark.junit4.AndroidBenchmarkRunner"
        }
    }
  4. برای افزودن معیار خود، یک نمونه از 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()
                );
           }
        }
    }

برای یادگیری نحوه نوشتن یک بنچمارک، از بخش «ایجاد یک کلاس میکروبنچمارک» عبور کنید.

تنظیمات کامل پروژه

برای تنظیم بنچمارک‌گیری منظم به جای بنچمارک‌گیری‌های تک‌مرحله‌ای، بنچمارک‌ها را در ماژول خودشان ایزوله کنید. این کار به اطمینان از این کمک می‌کند که پیکربندی آنها، مانند تنظیم debuggable روی false ، از تست‌های منظم جدا باشد.

از آنجا که Microbenchmark کد شما را مستقیماً اجرا می‌کند، کدی را که می‌خواهید بنچمارک کنید در یک ماژول Gradle جداگانه قرار دهید و همانطور که در شکل 1 نشان داده شده است، وابستگی را روی آن ماژول تنظیم کنید.

ساختار برنامه
شکل ۱. ساختار برنامه با ماژول‌های Gradle :app ، :microbenchmark و :benchmarkable که به Microbenchmarks اجازه می‌دهد کد را در ماژول :benchmarkable بنچمارک کند.

برای افزودن یک ماژول جدید Gradle، می‌توانید از ویزارد ماژول در اندروید استودیو استفاده کنید. ویزارد، ماژولی را ایجاد می‌کند که از قبل برای بنچمارک پیکربندی شده است، یک دایرکتوری بنچمارک به آن اضافه شده و debuggable روی false تنظیم شده است.

  1. روی پروژه یا ماژول خود در پنل Project در اندروید استودیو کلیک راست کرده و روی New > Module کلیک کنید.

  2. در قسمت قالب‌ها ، گزینه Benchmark را انتخاب کنید.

  3. Microbenchmark را به عنوان نوع ماژول بنچمارک انتخاب کنید.

  4. برای نام ماژول، عبارت "microbenchmark" را تایپ کنید.

  5. روی پایان کلیک کنید.

پیکربندی ماژول کتابخانه جدید
شکل ۲. اضافه کردن یک ماژول Gradle جدید در اندروید استودیو Bumblebee

پس از ایجاد ماژول، فایل 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 چندین بار اجرا می‌شود و می‌تواند بر زمان کلی مورد نیاز برای اجرای بنچمارک تأثیر بگذارد. اگر نیاز به تأیید برخی از نتایج یک بنچمارک دارید، می‌توانید به جای انجام آن در هر تکرار بنچمارک، آخرین نتیجه را تأیید کنید.

اجرای بنچمارک

در اندروید استودیو، همانطور که با هر @Test انجام می‌دهید، با استفاده از عمل حاشیه‌ای کنار کلاس یا متد تست خود، همانطور که در شکل 3 نشان داده شده است، معیار خود را اجرا کنید.

اجرای میکروبنچمارک
شکل ۳. اجرای تست Microbenchmark با استفاده از عمل حاشیه‌ای کنار کلاس تست.

روش دیگر، از خط فرمان، connectedCheck اجرا کنید تا تمام تست‌ها از ماژول Gradle مشخص شده اجرا شوند:

./gradlew benchmark:connectedCheck

یا یک تست واحد:

./gradlew benchmark:connectedCheck -P android.testInstrumentationRunnerArguments.class=com.example.benchmark.SampleBenchmark#benchmarkSomeWork

نتایج بنچمارک

پس از اجرای موفقیت‌آمیز میکروبنچمارک، معیارها مستقیماً در اندروید استودیو نمایش داده می‌شوند و یک گزارش کامل بنچمارک با معیارهای اضافی و اطلاعات دستگاه در قالب 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 قرار دارد.

خطاهای پیکربندی

این کتابخانه شرایط زیر را تشخیص می‌دهد تا اطمینان حاصل کند که پروژه و محیط شما برای عملکرد دقیق در زمان انتشار تنظیم شده‌اند:

  • اشکال‌زدایی (Debugable) روی 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_ آغاز می‌کند.

{% کلمه به کلمه %} {% فعل کمکی %} {% کلمه به کلمه %} {% فعل کمکی %}