معیار در ادغام مداوم

می‌توانید محک‌ها را در «ادغام مداوم» (CI) اجرا کنید تا عملکرد را درطول زمان پیگیری کنید و پسرفت‌های عملکردی (یا بهبودها) را حتی قبل‌از انتشار برنامه‌تان تشخیص دهید. این صفحه اطلاعات پایه‌ای درباره ارزیابی مقایسه‌ای در CI ارائه می‌دهد.

قبل‌از شروع محک‌زنی در CI، تفاوت ضبط و ارزیابی نتایج با آزمایش‌های معمولی را درنظر بگیرید.

نتایج فازی

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

استفاده از دستگاه‌های واقعی

اجرای محک‌ها در دستگاه‌های Android فیزیکی. اگرچه این آزمایش‌ها می‌توانند روی شبیه‌سازها اجرا شوند، اما این کار به‌شدت توصیه نمی‌شود زیرا تجربه کاربری واقعی را نشان نمی‌دهد و درعوض اعدادی را ارائه می‌دهد که به قابلیت‌های سخت‌افزاری و سیستم‌عامل میزبان وابسته هستند. استفاده از دستگاه‌های واقعی یا سرویسی را که به شما امکان می‌دهد آزمایش‌ها را در دستگاه‌های واقعی اجرا کنید، مانند Firebase Test Lab، مدنظر قرار دهید.

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

اجرای محک‌ها به‌عنوان بخشی از خط لوله CI شما ممکن است با اجرای آن به‌صورت محلی از Android Studio متفاوت باشد. به‌طور محلی، معمولاً آزمایش‌های ادغام Android را با یک تکلیف Gradle connectedCheck اجرا می‌کنید. این تکلیف به‌طور خودکار فایل APK و فایل APK آزمایشی شما را می‌سازد و آزمایش‌ها را در دستگاه(های) متصل به سرور CI اجرا می‌کند. هنگام اجرا در CI، این جریان معمولاً باید به فازهای جداگانه تقسیم شود.

ساخت

برای کتابخانه Microbenchmark، تکلیف Gradle assemble[VariantName]AndroidTest را اجرا کنید که فایل APK آزمایشی شما را ایجاد می‌کند که حاوی هم کد برنامه و هم کد آزمایش‌شده شما است.

یا اینکه کتابخانه Macrobenchmark از شما می‌خواهد APK هدف و APK آزمایشی را به‌طور جداگانه بسازید. بنابراین، تکلیف‌های Gradle :app:assemble[VariantName] و :macrobenchmark:assemble[VariantName] را اجرا کنید.

نصب و اجرا

این مراحل معمولاً بدون نیاز به اجرای تکالیف Gradle انجام می‌شوند. توجه داشته باشید که بسته به اینکه از سرویسی استفاده می‌کنید که به شما امکان می‌دهد آزمایش‌ها را روی دستگاه‌های واقعی اجرا کنید یا نه، ممکن است این موارد انتزاعی باشند.

برای نصب، از فرمان adb install استفاده کنید و APK آزمایشی یا APK هدف را مشخص کنید.

فرمان ابزار adb shell am را برای اجرای همه محک‌ها اجرا کنید:

adb shell am instrument -w com.example.benchmark/androidx.benchmark.junit4.AndroidBenchmarkRunner

هنگام استفاده از کتابخانه Macrobenchmark، از androidx.test.runner.AndroidJUnitRunner معمولی به‌عنوان اجراکننده ابزار دقیق استفاده کنید.

می‌توانید همان آرگومان‌های ابزار دقیق را که در پیکربندی Gradle وجود دارد بااستفاده از آرگومان -e ارسال کنید. برای همه گزینه‌های آرگومان‌های ابزار دقیق، آرگومان‌های ابزار دقیق Microbenchmark یا افزودن آرگومان‌های ابزار دقیق برای Macrobenchmark را ببینید.

برای مثال، می‌توانید آرگومان dryRunMode را برای اجرای ریزمعیارها به‌عنوان بخشی از فرایند درستی‌سنجی درخواست واکشی تنظیم کنید. با فعال کردن این پرچم، ریز محک‌ها فقط در یک حلقه اجرا می‌شوند و تأیید می‌کنند که به‌درستی اجرا می‌شوند اما اجرای آن‌ها خیلی طول نمی‌کشد.

adb shell am instrument -w -e "androidx.benchmark.dryRunMode.enable" "true" com.example.benchmark/androidx.benchmark.junit4.AndroidBenchmarkRunner

برای اطلاعات بیشتر درباره نحوه اجرای آزمایش‌های ابزار دقیق از خط فرمان، به اجرای آزمایش‌ها با ADB مراجعه کنید.

ساعت‌های صفحه قفل

افزونه Microbenchmark Gradle فرمان ./gradlew lockClocks را برای قفل کردن ساعت‌های CPU دستگاه ریشه‌دار ارائه می‌دهد. این کار برای اطمینان از پایداری مفید است وقتی به دستگاه‌های با دسترسی ریشه‌ای، مثل ساخت‌های «userdebug»، دسترسی دارید. می‌توانید این کار را با اسکریپت پوسته lockClocks.sh که در منبع کتابخانه دردسترس است تکرار کنید.

می‌توانید اسکریپت را مستقیماً از میزبان Linux یا Mac اجرا کنید، یا می‌توانید با چند فرمان adb آن را به دستگاه ارسال کنید:

adb push path/lockClocks.sh /data/local/tmp/lockClocks.sh
adb shell /data/local/tmp/lockClocks.sh
adb shell rm /data/local/tmp/lockClocks.sh

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

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

جمع‌آوری نتایج

کتابخانه‌های محک‌زنی اندازه‌گیری‌ها را در JSON، همراه با ردهای نمایه‌سازی در دایرکتوری‌ای در دستگاه Android پس‌از هر اجرای محک‌زنی خروجی می‌دهند. کتابخانه Macrobenchmark چندین فایل ردیابی perfetto را خروجی می‌دهد: یکی برای هر تکرار اندازه‌گیری‌شده از هر حلقه MacrobenchmarkRule.measureRepeated. اما Microbenchmark فقط یک فایل ردگیری برای همه تکرارهای هر BenchmarkRule.measureRepeated ایجاد می‌کند. فایل‌های ردیابی نمایه‌سازی نیز در همین فهرست راهنما خروجی داده می‌شوند.

ذخیره و پیدا کردن فایل‌ها

اگر محک‌ها را با Gradle اجرا کنید، این فایل‌ها به‌طور خودکار در دایرکتوری خروجی‌های رایانه میزبان شما در build/outputs/connected_android_test_additional_output/debugAndroidTest/connected/ کپی می‌شوند.

اگر مستقیماً با فرمان adb اجرا می‌کنید، باید فایل‌ها را به‌صورت دستی بکشید. به‌طور پیش‌فرض، گزارش‌ها در دستگاه در فهرست رسانه فضای ذخیره‌سازی خارجی برنامه آزمایش‌شده ذخیره می‌شوند. برای راحتی، کتابخانه مسیر فایل را در Logcat چاپ می‌کند. توجه داشته باشید که پوشه خروجی ممکن است بسته به اینکه محک‌ها در کدام نسخه Android اجرا می‌شوند متفاوت باشد.

Benchmark: writing results to /storage/emulated/0/Android/media/com.example.macrobenchmark/com.example.macrobenchmark-benchmarkData.json

همچنین می‌توانید مکانی را که گزارش‌های محک در دستگاه ذخیره می‌شود بااستفاده از آرگومان ابزار دقیق additionalTestOutputDir پیکربندی کنید. این پوشه باید توسط برنامه شما قابل‌نوشتن باشد.

adb shell am instrument -w -e additionalTestOutputDir /sdcard/Download/ com.example.benchmark/androidx.benchmark.junit4.AndroidBenchmarkRunner

در Android نسخه ۱۰ (سطح API‏ ۲۹) و بالاتر، آزمایش‌های برنامه‌تان به‌طور پیش‌فرض در جعبه امن ذخیره‌سازی اجرا می‌شود که از دسترسی برنامه‌تان به فایل‌های خارج از دایرکتوری مختص برنامه جلوگیری می‌کند. برای اینکه بتوانید در فهرست راهنمای سراسری، مثل /sdcard/Download، ذخیره کنید، متغیر مستقل ابزارسنجی زیر را عبور دهید:

-e no-isolated-storage true

همچنین باید به‌طور صریح گزینه‌های فضای ذخیره‌سازی قدیمی را در مانیفست محک خود مجاز کنید:

<application android:requestLegacyExternalStorage="true" ... >

برای اطلاعات بیشتر، انصراف موقت از فضای ذخیره‌سازی محدود را ببینید.

بازیابی فایل‌ها

برای بازیابی فایل‌های تولیدشده از دستگاه، از فرمان adb pull استفاده کنید که فایل مشخص‌شده را به دایرکتوری فعلی در میزبان شما می‌کشد:

adb pull /storage/emulated/0/Android/media/com.example.macrobenchmark/com.example.macrobenchmark-benchmarkData.json

برای بازیابی همه benchmarkData از پوشه‌ای مشخص، قطعه کد زیر را بررسی کنید:

# The following command pulls all files ending in -benchmarkData.json from the directory
# hierarchy starting at the root /storage/emulated/0/Android.
adb shell find /sdcard/Download -name "*-benchmarkData.json" | tr -d '\r' | xargs -n1 adb pull

فایل‌های ردیابی (.trace یا .perfetto-trace) در همان پوشه benchmarkData.json ذخیره می‌شوند، بنابراین می‌توانید آن‌ها را به همان روش جمع‌آوری کنید.

نمونه داده‌های محک‌زنی

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

{
    "context": {
        "build": {
            "brand": "google",
            "device": "blueline",
            "fingerprint": "google/blueline/blueline:12/SP1A.210812.015/7679548:user/release-keys",
            "model": "Pixel 3",
            "version": {
                "sdk": 31
            }
        },
        "cpuCoreCount": 8,
        "cpuLocked": false,
        "cpuMaxFreqHz": 2803200000,
        "memTotalBytes": 3753299968,
        "sustainedPerformanceModeEnabled": false
    },
    "benchmarks": [
        {
            "name": "startup",
            "params": {},
            "className": "com.example.macrobenchmark.startup.SampleStartupBenchmark",
            "totalRunTimeNs": 4975598256,
            "metrics": {
                "timeToInitialDisplayMs": {
                    "minimum": 347.881076,
                    "maximum": 347.881076,
                    "median": 347.881076,
                    "runs": [
                        347.881076
                    ]
                }
            },
            "sampledMetrics": {},
            "warmupIterations": 0,
            "repeatIterations": 3,
            "thermalThrottleSleepSeconds": 0
        }
    ]
}

منابع بیشتر