نوشتن Macrobenchmark

از کتابخانه Macrobenchmark برای آزمایش موارد استفاده بزرگ‌تر برنامه‌تان، ازجمله راه‌اندازی برنامه و دستکاری‌های پیچیده میانای کاربری، مانند پیمایش LazyColumn یا اجرای پویانمایی‌ها استفاده کنید. اگر می‌خواهید بخش‌های کوچک‌تری از کدتان را آزمایش کنید، Microbenchmark را ببینید. این صفحه نحوه راه‌اندازی کتابخانه Macrobenchmark را نشان می‌دهد.

این کتابخانه نتایج محک‌زنی را به کنسول «استودیو Android» و به یک فایل JSON با جزئیات بیشتر ارسال می‌کند. همچنین فایل‌های ردیابی ارائه می‌دهد که می‌توانید آن‌ها را در «استودیو Android» بارگیری و تجزیه‌وتحلیل کنید.

از کتابخانه Macrobenchmark در محیط ادغام پیوسته (CI) استفاده کنید، همان‌طور که در معیار در ادغام پیوسته شرح داده شده است.

می‌توانید از Macrobenchmark برای تولید «نمایه‌های پایه» استفاده کنید. ابتدا کتابخانه Macrobenchmark را راه‌اندازی کنید، سپس می‌توانید «نمایه پایه» ایجاد کنید.

Macrobenchmark ابزار توصیه‌شده برای آزمایش کردن میاناهای کاربر ایجادشده با Jetpack Compose است. برای آشنایی با نحوه نوشتن آزمایش‌های UI Automator که با گره‌های Compose شما تعامل دارند، به هم‌کنش‌پذیری مراجعه کنید.

راه‌اندازی پروژه

توصیه می‌کنیم از Macrobenchmark با جدیدترین نسخه Android Studio استفاده کنید.

راه‌اندازی کردن واحد Macrobenchmark

Macrobenchmark به یک واحد com.android.test نیاز دارد که از کد برنامه شما جدا است و مسئول اجرای آزمایش‌هایی است که برنامه شما را می‌سنجند.

در Android Studio، الگویی برای ساده‌سازی راه‌اندازی واحد Macrobenchmark دردسترس است. الگوی واحد محک‌زنی به‌طور خودکار واحدی در پروژه‌تان ایجاد می‌کند تا برنامه ساخته‌شده توسط واحد برنامه را اندازه‌گیری کند، ازجمله محک‌زنی راه‌اندازی نمونه.

برای استفاده از الگوی ماژول برای ایجاد ماژول جدید، کارهای زیر را انجام دهید:

  1. در پانل پروژه در «استودیو Android»، روی پروژه یا واحدتان کلیک راست کنید و جدید > واحد را انتخاب کنید.

  2. معیار را از پانل الگوها انتخاب کنید. می‌توانید برنامه هدف (یعنی برنامه‌ای که باید محک‌زنی شود) و همچنین نام بسته و ماژول را برای ماژول Macrobenchmark جدید سفارشی‌سازی کنید.

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

الگوی «واحد محک‌زنی».
شکل ۱. الگوی واحد محک.

راه‌اندازی برنامه

برای محک زدن برنامه (که به‌عنوان هدف Macrobenchmark شناخته می‌شود)، برنامه باید profileable باشد که امکان خواندن اطلاعات ردیابی دقیق را بدون تأثیر بر عملکرد فراهم می‌کند. جادوگر ماژول برچسب <profileable> را به‌طور خودکار به فایل AndroidManifest.xml برنامه اضافه می‌کند.

مطمئن شوید که برنامه هدف شامل ProfilerInstaller نسخه ۱.۳ یا جدیدتر باشد، که کتابخانه Macrobenchmark برای فعال کردن ضبط و بازنشانی نمایه و پاک کردن حافظه نهان سایه‌زن به آن نیاز دارد.

برنامه محک‌زده‌شده را تا حد امکان نزدیک به نسخه پخش یا تولید پیکربندی کنید. آن را به‌عنوان غیرقابل‌اشکال‌زدایی و ترجیحاً با فعال بودن کوچک‌سازی تنظیم کنید، که عملکرد را بهبود می‌بخشد. معمولاً این کار را با ایجاد نسخه‌ای از متغیر انتشار انجام می‌دهید که عملکرد یکسانی دارد اما به‌صورت محلی با کلیدهای اشکال‌زدایی امضا شده است. یا می‌توانید از initWith استفاده کنید تا به Gradle دستور دهید این کار را برای شما انجام دهد:

کاتلین

buildTypes {
    getByName("release") {
        isMinifyEnabled = true
        isShrinkResources = true
        proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"))
    }

    create("benchmark") {
        initWith(getByName("release"))
        signingConfig = signingConfigs.getByName("debug")
    }
}

شیک

buildTypes {
    release {
        isMinifyEnabled = true
        isShrinkResources = true
        proguardFiles(
            getDefaultProguardFile("proguard-android-optimize.txt"),
            "keep-rules.pro"
        )
        // In real app, this would use its own release keystore
        signingConfig = signingConfigs.getByName("debug")
        baselineProfile.automaticGenerationDuringBuild = true
    }
}

برای کمک به اطمینان از اینکه اجرای محک هم نسخه صحیح برنامه‌تان را می‌سازد و هم آن را آزمایش می‌کند، همان‌طور که در شکل ۲ نشان داده شده است، کارهای زیر را انجام دهید:

  1. همگام‌سازی Gradle را انجام دهید.
  2. پانل Build Variants (انواع ساخت) را باز کنید.
  3. نوع محک‌زنی هر دو برنامه و مدول Macrobenchmark را انتخاب کنید.
نوع محک را انتخاب کنید.
شکل ۲. گونه محک را انتخاب کنید.

(اختیاری) راه‌اندازی برنامه چندماژولی

اگر برنامه‌تان بیش‌از یک ماژول Gradle دارد، مطمئن شوید که اسکریپت‌های ساخت شما می‌دانند کدام تنوع ساخت را باید کامپایل کنند. ویژگی matchingFallbacks را به نوع ساخت benchmark از پیمانه‌های :macrobenchmark و :app اضافه کنید. بقیه پیمانه‌های Gradle شما می‌توانند همان پیکربندی قبلی را داشته باشند.

کاتلین

create("benchmark") {
    initWith(getByName("release"))
    signingConfig = signingConfigs.getByName("debug")

    matchingFallbacks += listOf("release")
 }

شیک

benchmark {
    initWith buildTypes.release
    signingConfig signingConfigs.debug

    matchingFallbacks = ['release']
 }

بدون این، نوع ساخت benchmark که به‌تازگی اضافه شده است باعث می‌شود ساخت ناموفق باشد و پیام خطای زیر را ارائه می‌دهد:

> Could not resolve project :shared.
     Required by:
         project :app
      > No matching variant of project :shared was found.
      ...

هنگام انتخاب تنوع‌های ساخت در پروژه‌تان، benchmark را برای مدول‌های :app و :macrobenchmark و release را برای هر مدول دیگری که در برنامه‌تان دارید انتخاب کنید، همان‌طور که در شکل ۳ نشان داده شده است:

گونه‌های محک برای پروژه چندماژولی با انواع ساخت محک و انتشار انتخاب‌شده.
شکل ۳.‏ گونه‌های محک برای پروژه چندماژولی با انواع ساخت محک و انتشار انتخاب‌شده.

برای اطلاعات بیشتر، حل کردن خطاهای ساخت مربوط به مطابقت دادن گونا را ببینید.

(اختیاری) راه‌اندازی نسخه‌های ویژه محصول

اگر چندین نسخه ویژه محصول در برنامه‌تان تنظیم شده است، واحد :macrobenchmark را پیکربندی کنید تا بداند کدام نسخه ویژه محصول برنامه‌تان را بسازد و محک بزند.

نمونه‌های این صفحه از دو نسخه ویژه محصول در واحد :app استفاده می‌کنند، demo و production، همان‌طور که در قطعه کد زیر نشان داده شده است:

کاتلین

flavorDimensions += "environment"
productFlavors {
    create("demo") {
        dimension = "environment"
        // ...
    }
    create("production") {
        dimension = "environment"
        // ...
    }
}

شیک

flavorDimensions 'environment'
productFlavors {
    demo {
        dimension 'environment'
        // ...
    }

    production {
        dimension 'environment'
        // ...
    }
}

بدون این پیکربندی، ممکن است خطای ساخت مشابه خطایی که توسط چند ماژول Gradle ایجاد می‌شود دریافت کنید:

Could not determine the dependencies of task ':macrobenchmark:connectedBenchmarkAndroidTest'.
> Could not determine the dependencies of null.
   > Could not resolve all task dependencies for configuration ':macrobenchmark:benchmarkTestedApks'.
      > Could not resolve project :app.
        Required by:
            project :macrobenchmark
         > The consumer was configured to find a runtime of a component, as well as attribute 'com.android.build.api.attributes.BuildTypeAttr' with value 'benchmark', attribute 'com.android.build.api.attributes.AgpVersionAttr' with value '7.3.0'. However we cannot choose between the following variants of project :app:
             -   demoBenchmarkRuntimeElements
             -   productionBenchmarkRuntimeElements
           All of them match the consumer attributes:
           ...

دو بخش زیر روش‌های پیکربندی محک‌زنی با چند نسخه ویژه محصول را شرح می‌دهند.

استفاده از missingDimensionStrategy

مشخص کردن missingDimensionStrategy در defaultConfig از مدول :macrobenchmark به سیستم ساخت می‌گوید که به پیمانه طعم برگردد. اگر ابعاد موردنظرتان را در واحد پیدا نکردید، مشخص کنید از کدام ابعاد استفاده شود. در مثال زیر، از طعم production به‌عنوان بُعد پیش‌فرض استفاده می‌شود:

کاتلین

defaultConfig {
    missingDimensionStrategy("environment", "production")
}

شیک

defaultConfig {
    missingDimensionStrategy "environment", "production"
}

به‌این‌ترتیب، واحد :macrobenchmark می‌تواند فقط نسخه ویژه محصول مشخص‌شده را بسازد و محک بزند، که اگر بدانید فقط یک نسخه ویژه محصول پیکربندی مناسبی برای محک زدن دارد، مفید است.

تعریف کردن نسخه‌های ویژه محصول در مدول :macrobenchmark

اگر می‌خواهید نسخه‌های ویژه محصول دیگری را بسازید و محک بزنید، آن‌ها را در مدول :macrobenchmark تعریف کنید. آن را مشابه با آنچه در واحد :app است مشخص کنید، اما فقط productFlavors را به dimension اختصاص دهید. تنظیمات دیگری لازم نیست:

کاتلین

flavorDimensions += "environment"
productFlavors {
    create("demo") {
        dimension = "environment"
    }
    create("production") {
        dimension = "environment"
    }
}

شیک

flavorDimensions 'environment'
productFlavors {
    demo {
        dimension 'environment'
    }

    production {
        dimension 'environment'
    }
}

پس‌از تعریف و همگام‌سازی پروژه، تنوع ساخت مربوطه را از پانل تنوع‌های ساخت انتخاب کنید، همان‌طور که در شکل ۴ نشان داده شده است:

نمونه‌های معیار برای پروژه با نسخه‌های ویژه محصول که productionBenchmark و release را به‌عنوان انتخاب‌شده نشان می‌دهد.
شکل ۴. انواع محک برای پروژه با نسخه‌های ویژه محصول که «محک تولید» و «انتشار» را به‌عنوان انتخاب‌شده نشان می‌دهد.

برای اطلاعات بیشتر، حل کردن خطاهای ساخت مربوط به مطابقت دادن گونا را ببینید.

ایجاد کلاس Macrobenchmark

آزمایش محک ازطریق میانای برنامه‌سازی کاربردی قانون MacrobenchmarkRule JUnit4 در کتابخانه Macrobenchmark ارائه می‌شود. این کلاس حاوی روش measureRepeated است که به شما امکان می‌دهد شرایط مختلفی را برای نحوه اجرا و محک‌زنی برنامه هدف مشخص کنید.

باید حداقل packageName برنامه هدف، آنچه را که metrics می‌خواهید اندازه‌گیری کنید، و تعداد دفعاتی iterations را که محک باید اجرا شود مشخص کنید.

کاتلین

@LargeTest
@RunWith(AndroidJUnit4::class)
class SampleStartupBenchmark {
    @get:Rule
    val benchmarkRule = MacrobenchmarkRule()

    @Test
    fun startup() = benchmarkRule.measureRepeated(
        packageName = TARGET_PACKAGE,
        metrics = listOf(StartupTimingMetric()),
        iterations = DEFAULT_ITERATIONS,
    ) {
        // starts default launch activity
        uiAutomator { startApp(TARGET_PACKAGE) }
    }
}

برای دیدن همه گزینه‌های سفارشی‌سازی محک، به بخش سفارشی‌سازی محک‌ها مراجعه کنید.

معیار تعاملات واسط کاربر Compose

درحالی‌که مثال قبلی راه‌اندازی برنامه را اندازه‌گیری می‌کند، اغلب می‌خواهید عملکرد واسط کاربر را اندازه‌گیری کنید، مانند افت فریم (jank) هنگام پیمایش.

برای محک‌زنی برنامه Jetpack Compose، مثلاً برای اندازه‌گیری FrameTimingMetric هنگام پیمایش LazyColumn، می‌توانید از UI Automator برای تعامل مستقیم با گره‌های Compose استفاده کنید، همان‌طور که در قطعه کد زیر نشان داده شده است.

@LargeTest
@RunWith(AndroidJUnit4::class)
class ComposeScrollBenchmark {
    @get:Rule
    val benchmarkRule = MacrobenchmarkRule()

    @Test
    fun scrollLazyColumn() = benchmarkRule.measureRepeated(
        packageName = "com.example.compose.app",
        metrics = listOf(FrameTimingMetric()),
        iterations = 5,
        startupMode = StartupMode.WARM,
        setupBlock = { pressHome() }
    ) {
        startActivityAndWait()

        // Find the Compose node using the testTag defined in your app
        val lazyColumn = device.findObject(By.res("my_lazy_column"))

        // Simulate a scroll gesture to measure FrameTimingMetric
        lazyColumn.setGestureMargin(device.displayWidth / 5)
        lazyColumn.fling(Direction.DOWN)
    }
}

اجرای محک‌زنی

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

Macrobenchmark را با کنش حاشیه در کنار کلاس آزمایش اجرا کنید.
شکل ۵. Macrobenchmark را با کنش حاشیه کنار کلاس آزمایش اجرا کنید.

همچنین می‌توانید با اجرای فرمان connectedCheck، همه محک‌ها را در یک ماژول Gradle از خط فرمان اجرا کنید:

./gradlew :macrobenchmark:connectedCheck

با اجرای دستور زیر می‌توانید یک آزمایش تکی اجرا کنید:

./gradlew :macrobenchmark:connectedCheck -P android.testInstrumentationRunnerArguments.class=com.example.macrobenchmark.startup.SampleStartupBenchmark#startup

برای اطلاعات درباره نحوه اجرا و نظارت بر محک‌ها در ادغام مداوم، محک در ادغام مداوم را ببینید.

نتایج محک‌زنی

پس‌از اجرای موفقیت‌آمیز محک، سنجه‌ها مستقیماً در Android Studio نمایش داده می‌شوند و برای استفاده CI در یک فایل JSON خروجی داده می‌شوند. هر تکرار اندازه‌گیری‌شده ردیابی سیستم جداگانه‌ای را ضبط می‌کند. می‌توانید این نتایج ردیابی را با کلیک کردن روی پیوندهای موجود در قاب نتایج آزمایش باز کنید، همان‌طور که در شکل ۶ نشان داده شده است:

نتایج راه‌اندازی Macrobenchmark.
شکل ۶.‏ نتایج راه‌اندازی Macrobenchmark.

وقتی ردیابی بار شد، «استودیو Android» از شما می‌خواهد فرایند موردنظر را برای تجزیه‌وتحلیل انتخاب کنید. انتخاب با فرایند برنامه هدف ازپیش تکمیل شده است، همان‌طور که در شکل ۷ نشان داده شده است:

انتخاب فرایند ردیابی Studio.
شکل ۷. انتخاب فرایند ردیابی استودیو.

پس‌از بار شدن فایل ردگیری، Studio نتایج را در ابزار تحلیل‌گر واحد پردازش مرکزی نشان می‌دهد:

ردیابی Studio.
شکل ۸. ردیابی استودیو.

گزارش‌های JSON و هرگونه رد نمایه‌سازی نیز به‌طور خودکار از دستگاه به میزبان کپی می‌شود. این موارد در دستگاه میزبان در مکان زیر نوشته شده‌اند:

project_root/module/build/outputs/connected_android_test_additional_output/debugAndroidTest/connected/device_id/

دسترسی دستی به فایل‌های ردیابی

اگر می‌خواهید از ابزار Perfetto برای تجزیه‌وتحلیل فایل ردگیری استفاده کنید، مراحل اضافه‌ای وجود دارد. Perfetto به شما امکان می‌دهد همه فرایندهایی را که درطول ردیابی در دستگاه اتفاق می‌افتد بازرسی کنید، درحالی‌که تحلیل‌گر واحد پردازش مرکزی Android Studio بازرسی را به یک فرایند محدود می‌کند.

اگر آزمایش‌ها را از Android Studio یا از خط فرمان Gradle فراخوانی کنید، فایل‌های ردیابی به‌طور خودکار از دستگاه به میزبان کپی می‌شوند. این موارد در دستگاه میزبان در مکان زیر نوشته شده است:

project_root/module/build/outputs/connected_android_test_additional_output/debugAndroidTest/connected/device_id/TrivialStartupBenchmark_startup[mode=COLD]_iter002.perfetto-trace

وقتی فایل ردیابی را در سیستم میزبان خود دارید، می‌توانید آن را در Android Studio با فایل > باز کردن در منو باز کنید. این تصویر نمای ابزار نمایه‌ساز را که در بخش قبلی نشان داده شد نمایش می‌دهد.

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

اگر برنامه به‌درستی پیکربندی نشده باشد (قابل‌اشکال‌زدایی یا غیرقابل‌نمایه‌سازی باشد)، Macrobenchmark به‌جای گزارش اندازه‌گیری نادرست یا ناقص، خطا برمی‌گرداند. می‌توانید این خطاها را با آرگومان androidx.benchmark.suppressErrors سرکوب کنید.

Macrobenchmark همچنین هنگام تلاش برای اندازه‌گیری شبیه‌ساز یا در دستگاهی با باتری کم، خطاهایی را برمی‌گرداند که ممکن است دسترسی به هسته و سرعت ساعت را به خطر بیندازد.

سفارشی‌سازی کردن محک‌ها

تابع measureRepeated پارامترهای مختلفی را می‌پذیرد که بر معیارهایی که کتابخانه جمع‌آوری می‌کند، نحوه شروع و کامپایل شدن برنامه، یا تعداد تکرارهای اجرای محک تأثیر می‌گذارند.

ثبت سنجه‌ها

سنجه‌ها نوع اصلی اطلاعاتی هستند که از محک‌های شما استخراج می‌شوند. سنجه‌های زیر دردسترس است:

برای اطلاعات بیشتر درباره سنجه‌ها، به ضبط سنجه‌های Macrobenchmark مراجعه کنید.

بهبود داده‌های ردیابی با رویدادهای سفارشی

مفید است که برنامه‌تان را با رویدادهای ردیابی سفارشی مجهز کنید، که با بقیه گزارش ردیابی دیده می‌شوند و می‌توانند به اشاره به مشکلات خاص برنامه‌تان کمک کنند. برای کسب اطلاعات بیشتر درباره ایجاد رویدادهای ردیابی سفارشی، به تعریف رویدادهای سفارشی مراجعه کنید.

CompilationMode

Macrobenchmark می‌تواند CompilationMode را مشخص کند که تعیین می‌کند چه مقدار از برنامه باید از بایت‌کد DEX (قالب بایت‌کد در APK) به کد ماشینی (مشابه C++‎ پیش‌کامپایل‌شده) پیش‌کامپایل شود.

به‌طور پیش‌فرض، Macrobenchmark با CompilationMode.DEFAULT اجرا می‌شود که «نمایه پایه» (درصورت دردسترس بودن) را در Android 7 (سطح میانای برنامه‌سازی کاربردی ۲۴) و نسخه‌های جدیدتر نصب می‌کند. اگر از Android 6 (سطح میانای برنامه‌سازی کاربردی ۲۳) یا نسخه‌های قدیمی‌تر استفاده می‌کنید، حالت کامپایل کردن به‌طور کامل فایل APK را به‌عنوان رفتار پیش‌فرض سیستم کامپایل می‌کند.

اگر برنامه هدف هم حاوی «نمایه پایه» و هم کتابخانه ProfileInstaller باشد، می‌توانید «نمایه پایه» را نصب کنید.

در Android 7 و نسخه‌های جدیدتر، می‌توانید CompilationMode را سفارشی‌سازی کنید تا بر میزان پیش‌کامپایل درون‌دستگاهی تأثیر بگذارد و سطوح مختلف کامپایل پیش‌از موعد (AOT) یا ذخیره‌سازی JIT را شبیه‌سازی کند. CompilationMode.Full، CompilationMode.Partial، CompilationMode.None، و CompilationMode.Ignore را ببینید.

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

StartupMode

برای اجرای شروع فعالیت، می‌توانید حالت راه‌اندازی ازپیش تعریف‌شده‌ای را ارسال کنید: COLD، WARM، یا HOT. این پارامتر نحوه راه‌اندازی فعالیت و وضعیت فرایند را در شروع آزمایش تغییر می‌دهد.

برای کسب اطلاعات بیشتر درباره انواع راه‌اندازی، به زمان راه‌اندازی برنامه مراجعه کنید.

نمونه‌ها

پروژه نمونه در Macrobenchmark Sample مخزن در GitHub دردسترس است.

ارائه کردن بازخورد

برای گزارش کردن مشکلات یا ارسال درخواست ویژگی برای Jetpack Macrobenchmark، ردیاب مشکل عمومی را ببینید.