اشکال‌زدایی نمایه‌های مبنا

این سند روال‌های مطلوب و مراحل عیب‌یابی را برای کمک به تشخیص مشکلات و اطمینان از عملکرد صحیح «نمایه‌های پایه» شما ارائه می‌دهد تا بیشترین بهره را ببرید.

مشکلات ساخت

اگر نمونه «نمایه‌های پایه» را در برنامه نمونه اکنون در Android کپی کرده باشید، ممکن است درطول تکلیف «نمایه پایه» با آزمایش‌های ناموفق مواجه شوید که نشان می‌دهد آزمایش‌ها نمی‌توانند در شبیه‌ساز اجرا شوند:

./gradlew assembleDemoRelease
Starting a Gradle Daemon (subsequent builds will be faster)
Calculating task graph as no configuration cache is available for tasks: assembleDemoRelease
Type-safe project accessors is an incubating feature.

> Task :benchmarks:pixel6Api33DemoNonMinifiedReleaseAndroidTest
Starting 14 tests on pixel6Api33

com.google.samples.apps.nowinandroid.foryou.ScrollForYouFeedBenchmark > scrollFeedCompilationNone[pixel6Api33] FAILED
        java.lang.AssertionError: ERRORS (not suppressed): EMULATOR
        WARNINGS (suppressed):
        ...

این خطاها به این دلیل رخ می‌دهند که «اکنون در Android» از دستگاه تحت مدیریت Gradle برای تولید «نمایه پایه» استفاده می‌کند. این شکست‌ها قابل‌انتظار است، زیرا معمولاً نباید محک‌های عملکرد را روی شبیه‌ساز اجرا کنید. بااین‌حال، چون هنگام تولید «نمایه‌های مبنا» سنجه‌های عملکرد را جمع‌آوری نمی‌کنید، می‌توانید برای راحتی کار، مجموعه «نمایه مبنا» را در شبیه‌سازها اجرا کنید. برای استفاده از Baseline Profiles با شبیه‌ساز، ساخت و نصب را از خط فرمان انجام دهید و آرگومانی را برای فعال کردن قوانین Baseline Profiles تنظیم کنید:

installDemoRelease -Pandroid.testInstrumentationRunnerArguments.androidx.benchmark.enabledRules=BaselineProfile

همچنین می‌توانید با انتخاب اجرا > ویرایش پیکربندی‌ها، پیکربندی اجرای سفارشی در «استودیو Android» ایجاد کنید تا «نمایه‌های پایه» را در شبیه‌سازها فعال کنید:

افزودن پیکربندی اجرای سفارشی برای ایجاد Baseline Profiles در «اکنون در Android»
شکل ۱. پیکربندی اجرای سفارشی را برای ایجاد «نمایه‌های پایه» در «اکنون در Android» اضافه کنید.

درستی‌سنجی نصب نمایه و برنامه

برای بررسی اینکه APK یا Android App Bundle (AAB) که درحال بازرسی آن هستید از یک تنوع ساخت است که شامل Baseline Profiles می‌شود، کارهای زیر را انجام دهید:

  1. در «استودیو Android»، ساختن > تجزیه‌وتحلیل APK را انتخاب کنید.
  2. AAB یا APK خود را باز کنید.
  3. تأیید کنید که فایل baseline.prof وجود دارد:

    • اگر درحال بازرسی AAB هستید، نمایه در /BUNDLE-METADATA/com.android.tools.build.profiles/baseline.prof است.
    • اگر APK را بازرسی می‌کنید، نمایه در /assets/dexopt/baseline.prof است.

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

      بررسی کردن «نمایه پایه» بااستفاده از «تحلیل‌کننده APK» در «استودیو Android»
      شکل ۲. بااستفاده از «تحلیل‌کننده APK» در «استودیو Android»، وجود «نمایه پایه» را بررسی کنید.

«نمایه‌های پایه» باید در دستگاهی که برنامه را اجرا می‌کند کامپایل شوند. وقتی ساخت‌های غیرقابل‌اشکال‌زدایی را بااستفاده از Android Studio یا ابزار خط فرمان Gradle wrapper نصب می‌کنید، کامپایل درون‌دستگاهی به‌طور خودکار انجام می‌شود. اگر برنامه را از «فروشگاه Google Play» نصب کنید، «نمایه‌های Baseline» درطول به‌روزرسانی‌های پس‌زمینه دستگاه کامپایل می‌شوند، نه در زمان نصب. وقتی برنامه بااستفاده از ابزارهای دیگر نصب می‌شود، کتابخانه Jetpack ProfileInstaller مسئول قرار دادن نمایه‌ها در صف برای کامپایل کردن درطول فرایند بهینه‌سازی DEX پس‌زمینه بعدی است.

در این موارد، اگر می‌خواهید مطمئن شوید که از «نمایه‌های مبنا» شما استفاده می‌شود، ممکن است لازم باشد «نمایه‌های مبنا» را به‌اجبار کامپایل کنید. ProfileVerifier به شما امکان می‌دهد وضعیت نصب و کامپایل نمایه را جستجو کنید، همان‌طور که در مثال زیر نشان داده شده است:

کاتلین

private const val TAG = "MainActivity"

class MainActivity : ComponentActivity() {
  ...
  override fun onResume() {
    super.onResume()
    lifecycleScope.launch {
      logCompilationStatus()
    }
  }

  private suspend fun logCompilationStatus() {
     withContext(Dispatchers.IO) {
        val status = ProfileVerifier.getCompilationStatusAsync().await()
        when (status.profileInstallResultCode) {
            RESULT_CODE_NO_PROFILE ->
                Log.d(TAG, "ProfileInstaller: Baseline Profile not found")
            RESULT_CODE_COMPILED_WITH_PROFILE ->
                Log.d(TAG, "ProfileInstaller: Compiled with profile")
            RESULT_CODE_PROFILE_ENQUEUED_FOR_COMPILATION ->
                Log.d(TAG, "ProfileInstaller: Enqueued for compilation")
            RESULT_CODE_COMPILED_WITH_PROFILE_NON_MATCHING ->
                Log.d(TAG, "ProfileInstaller: App was installed through Play store")
            RESULT_CODE_ERROR_PACKAGE_NAME_DOES_NOT_EXIST ->
                Log.d(TAG, "ProfileInstaller: PackageName not found")
            RESULT_CODE_ERROR_CACHE_FILE_EXISTS_BUT_CANNOT_BE_READ ->
                Log.d(TAG, "ProfileInstaller: Cache file exists but cannot be read")
            RESULT_CODE_ERROR_CANT_WRITE_PROFILE_VERIFICATION_RESULT_CACHE_FILE ->
                Log.d(TAG, "ProfileInstaller: Can't write cache file")
            RESULT_CODE_ERROR_UNSUPPORTED_API_VERSION ->
                Log.d(TAG, "ProfileInstaller: Enqueued for compilation")
            else ->
                Log.d(TAG, "ProfileInstaller: Profile not compiled or enqueued")
        }
    }
}

جاوا

public class MainActivity extends ComponentActivity {

    private static final String TAG = "MainActivity";

    @Override
    protected void onResume() {
        super.onResume();

        logCompilationStatus();
    }

    private void logCompilationStatus() {
         ListeningExecutorService service = MoreExecutors.listeningDecorator(
                Executors.newSingleThreadExecutor());
        ListenableFuture<ProfileVerifier.CompilationStatus> future =
                ProfileVerifier.getCompilationStatusAsync();
        Futures.addCallback(future, new FutureCallback<>() {
            @Override
            public void onSuccess(CompilationStatus result) {
                int resultCode = result.getProfileInstallResultCode();
                if (resultCode == RESULT_CODE_NO_PROFILE) {
                    Log.d(TAG, "ProfileInstaller: Baseline Profile not found");
                } else if (resultCode == RESULT_CODE_COMPILED_WITH_PROFILE) {
                    Log.d(TAG, "ProfileInstaller: Compiled with profile");
                } else if (resultCode == RESULT_CODE_PROFILE_ENQUEUED_FOR_COMPILATION) {
                    Log.d(TAG, "ProfileInstaller: Enqueued for compilation");
                } else if (resultCode == RESULT_CODE_COMPILED_WITH_PROFILE_NON_MATCHING) {
                    Log.d(TAG, "ProfileInstaller: App was installed through Play store");
                } else if (resultCode == RESULT_CODE_ERROR_PACKAGE_NAME_DOES_NOT_EXIST) {
                    Log.d(TAG, "ProfileInstaller: PackageName not found");
                } else if (resultCode == RESULT_CODE_ERROR_CACHE_FILE_EXISTS_BUT_CANNOT_BE_READ) {
                    Log.d(TAG, "ProfileInstaller: Cache file exists but cannot be read");
                } else if (resultCode
                        == RESULT_CODE_ERROR_CANT_WRITE_PROFILE_VERIFICATION_RESULT_CACHE_FILE) {
                    Log.d(TAG, "ProfileInstaller: Can't write cache file");
                } else if (resultCode == RESULT_CODE_ERROR_UNSUPPORTED_API_VERSION) {
                    Log.d(TAG, "ProfileInstaller: Enqueued for compilation");
                } else {
                    Log.d(TAG, "ProfileInstaller: Profile not compiled or enqueued");
                }
            }

            @Override
            public void onFailure(Throwable t) {
                Log.d(TAG,
                        "ProfileInstaller: Error getting installation status: " + t.getMessage());
            }
        }, service);
    }
}

کدهای نتیجه زیر نکاتی را درباره علت برخی مشکلات ارائه می‌دهند:

RESULT_CODE_COMPILED_WITH_PROFILE
نمایه نصب و کامپایل می‌شود و هرزمان برنامه اجرا شود از آن استفاده می‌شود. این نتیجه‌ای است که می‌خواهید ببینید.
RESULT_CODE_ERROR_NO_PROFILE_EMBEDDED
هیچ نمایه‌ای در APK درحال اجرا پیدا نشد. اگر این خطا را می‌بینید، مطمئن شوید که از تنوع ساختی استفاده می‌کنید که شامل «نمایه‌های پایه» است و APK حاوی نمایه است.
RESULT_CODE_NO_PROFILE
هنگام نصب برنامه ازطریق فروشگاه برنامه یا مدیر بسته، هیچ نمایه‌ای برای این برنامه نصب نشده است. دلیل اصلی این کد خطا این است که نصب‌کننده نمایه به‌دلیل غیرفعال بودن ProfileInstallerInitializer اجرا نشد. توجه داشته باشید که وقتی این خطا گزارش می‌شود، نمایه جاسازی‌شده همچنان در APK برنامه پیدا می‌شود. وقتی نمایه جاسازی‌شده‌ای پیدا نشود، کد خطای برگردانده‌شده RESULT_CODE_ERROR_NO_PROFILE_EMBEDDED است.
RESULT_CODE_PROFILE_ENQUEUED_FOR_COMPILATION
نمایه‌ای در APK یا AAB پیدا شد و برای کامپایل در صف قرار گرفت. وقتی نمایه‌ای توسط ProfileInstaller نصب می‌شود، برای همگردانی در دفعه بعدی که بهینه‌سازی DEX پس‌زمینه توسط سیستم اجرا می‌شود در صف قرار می‌گیرد. نمایه تا زمانی که گردآوری تکمیل نشود فعال نیست. تا زمانی که کامپایل کردن تکمیل نشده است، برای محک زدن «نمایه‌های خط پایه» خود تلاش نکنید. ممکن است لازم باشد کامپایل کردن «نمایه‌های پایه» را اجباری کنید. این خطا هنگام نصب برنامه از «فروشگاه Play» یا مدیر بسته در دستگاه‌های دارای Android نسخه ۹ (میانای برنامه‌سازی کاربردی ۲۸) و بالاتر رخ نخواهد داد، زیرا کامپایل کردن درطول نصب انجام می‌شود.
RESULT_CODE_COMPILED_WITH_PROFILE_NON_MATCHING
نمایه غیرمنطبق نصب شده است و برنامه با آن کامپایل شده است. این نتیجه نصب ازطریق «فروشگاه Google Play» یا مدیر بسته است. توجه داشته باشید که این نتیجه با RESULT_CODE_COMPILED_WITH_PROFILE متفاوت است زیرا نمایه غیرمنطبق فقط روش‌هایی را کامپایل می‌کند که هنوز بین نمایه و برنامه مشترک هستند. نمایه درواقع کوچک‌تر از حد انتظار است و روش‌های کمتری نسبت‌به آنچه در «نمایه پایه» گنجانده شده است کامپایل خواهد شد.
RESULT_CODE_ERROR_CANT_WRITE_PROFILE_VERIFICATION_RESULT_CACHE_FILE
ProfileVerifier نمی‌تواند فایل حافظه نهان نتیجه درستی‌سنجی را بنویسد. این مشکل می‌تواند به‌دلیل وجود اشکال در اجازه‌های پوشه برنامه یا کافی نبودن فضای دیسک آزاد در دستگاه باشد.
RESULT_CODE_ERROR_UNSUPPORTED_API_VERSION
ProfileVerifieris running on an unsupported API version of Android. ProfileVerifier فقط از Android 9 (سطح میانای برنامه‌سازی کاربردی ۲۸) و بالاتر پشتیبانی می‌کند.
RESULT_CODE_ERROR_PACKAGE_NAME_DOES_NOT_EXIST
هنگام پرسمان PackageManager برای بسته برنامه، PackageManager.NameNotFoundException ایجاد می‌شود. این اتفاق به‌ندرت رخ می‌دهد. برنامه را حذف نصب کنید و همه چیز را بازنصب کنید.
RESULT_CODE_ERROR_CACHE_FILE_EXISTS_BUT_CANNOT_BE_READ
فایل حافظه نهان نتیجه درستی‌سنجی قبلی وجود دارد، اما خوانده نمی‌شود. این به‌ندرت اتفاق می‌افتد. برنامه را حذف نصب کنید و همه چیز را بازنصب کنید.

استفاده از ProfileVerifier در تولید

در تولید، می‌توانید از ProfileVerifier همراه با کتابخانه‌های گزارش‌دهی تجزیه‌وتحلیل، مانند Google Analytics برای Firebase، برای تولید رویدادهای تجزیه‌وتحلیل که وضعیت نمایه را نشان می‌دهند استفاده کنید. برای مثال، اگر نسخه جدیدی از برنامه منتشر شود که فاقد «نمایه‌های پایه» باشد، این ویژگی به‌سرعت به شما هشدار می‌دهد.

اجبار به کامپایل کردن «نمایه‌های مبنا»

اگر وضعیت کامپایل «نمایه‌های مبنا» شما RESULT_CODE_PROFILE_ENQUEUED_FOR_COMPILATION است، می‌توانید بااستفاده از adb کامپایل فوری را اجباری کنید:

adb shell cmd package compile -r bg-dexopt PACKAGE_NAME

بررسی وضعیت کامپایل «نمایه مبنا» بدون ProfileVerifier

اگر از ProfileVerifier استفاده نمی‌کنید، می‌توانید وضعیت کامپایل را بااستفاده از adb بررسی کنید، هرچند اطلاعات آماری عمیقی مثل ProfileVerifier ارائه نمی‌دهد:

adb shell dumpsys package dexopt | grep -A 2 PACKAGE_NAME

استفاده از adb چیزی شبیه به موارد زیر تولید می‌کند:

  [com.google.samples.apps.nowinandroid.demo]
    path: /data/app/~~dzJiGMKvp22vi2SsvfjkrQ==/com.google.samples.apps.nowinandroid.demo-7FR1sdJ8ZTy7eCLwAnn0Vg==/base.apk
      arm64: [status=speed-profile] [reason=bg-dexopt] [primary-abi]
        [location is /data/app/~~dzJiGMKvp22vi2SsvfjkrQ==/com.google.samples.apps.nowinandroid.demo-7FR1sdJ8ZTy7eCLwAnn0Vg==/oat/arm64/base.odex]

مقدار وضعیت نشان‌دهنده وضعیت گردآوری نمایه است و یکی از مقادیر زیر است:

وضعیت گردآوری معنی
speed‑profile نمایه کامپایل‌شده وجود دارد و درحال استفاده است.
verify نمایه کامپایل‌شده‌ای وجود ندارد.

وضعیت verify به این معنی نیست که APK یا AAB حاوی نمایه نیست، زیرا می‌تواند برای کامپایل شدن توسط تکلیف بهینه‌سازی DEX پس‌زمینه بعدی در صف قرار گیرد.

مقدار دلیل نشان می‌دهد چه چیزی باعث کامپایل نمایه می‌شود و یکی از مقادیر زیر است:

دلیل معنی
install‑dm «نمایه پایه» به‌صورت دستی یا توسط Google Play هنگام نصب برنامه کامپایل شده است.
bg‑dexopt وقتی دستگاهتان در حالت آزاد بود، نمایه‌ای گردآوری شد. این ممکن است یک «نمایه پایه» باشد، یا ممکن است نمایه‌ای باشد که درطول استفاده از برنامه جمع‌آوری شده است.
cmdline کامپایل بااستفاده از adb راه‌اندازی شد. این ممکن است یک «نمایه پایه» باشد، یا ممکن است نمایه‌ای باشد که درطول استفاده از برنامه جمع‌آوری شده است.

درستی‌سنجی درخواست «نمایه استارتاپ» برای DEX و r8.json

قوانین «نمایه راه‌اندازی» در زمان ساخت توسط R8 برای بهینه‌سازی چیدمان کلاس‌ها در فایل‌های DEX شما استفاده می‌شود. این بهینه‌سازی زمان ساخت با نحوه استفاده از «نمایه‌های پایه» (baseline.prof) متفاوت است، زیرا آن‌ها در APK یا AAB بسته‌بندی می‌شوند تا ART بتواند کامپایل درون‌دستگاهی را انجام دهد. چون قوانین «نمایه راه‌اندازی» درطول فرایند ساخت اعمال می‌شود، فایل startup.prof جداگانه‌ای در APK یا AAB شما برای بازرسی وجود ندارد. درعوض، تأثیر «نمایه‌های راه‌اندازی» در چیدمان فایل DEX قابل‌مشاهده است.

بررسی آرایش DEX با r8.json (توصیه‌شده برای AGP نسخه ۸.۸ یا بالاتر)

برای پروژه‌هایی که از «افزایه Android Gradle»‏ (AGP) نسخه ۸.۸ یا بالاتر استفاده می‌کنند، می‌توانید با بررسی فایل r8.json تولیدشده، درستی‌سنجی کنید که آیا «نمایه راه‌اندازی» اعمال شده است یا نه. این فایل در بسته AAB شما قرار دارد.

  1. بایگانی AAB را باز کنید و فایل r8.json را پیدا کنید.
  2. فایل را برای آرایه dexFiles جستجو کنید، که فایل‌های DEX تولیدشده را فهرست می‌کند.
  3. به‌دنبال شیء dexFiles بگردید که حاوی جفت کلید-مقدار "startup": true باشد. این به‌طور صریح نشان می‌دهد که قوانین Startup Profile برای بهینه‌سازی چیدمان آن فایل DEX خاص اعمال شده است.

    "dexFiles": [
     {
       "checksum": "...",
       "startup": true // This flag confirms profile application to this DEX file
     },
     // ... other DEX files
    ]
    

بررسی کردن ترتیب DEX برای همه نسخه‌های AGP

اگر از نسخه AGP پایین‌تر از ۸.۸ استفاده می‌کنید، بازرسی فایل‌های DEX روش اصلی برای تأیید اعمال صحیح «نمایه راه‌اندازی» شما است. اگر از AGP نسخه ۸.۸ یا بالاتر استفاده می‌کنید و می‌خواهید چیدمان DEX را به‌صورت دستی بررسی کنید، می‌توانید از این روش نیز استفاده کنید. برای مثال، اگر بهبود عملکرد موردانتظار را نمی‌بینید. برای بازرسی ترتیب DEX، کارهای زیر را انجام دهید:

  1. AAB یا APK خود را بااستفاده از ساخت > تجزیه‌وتحلیل APK در Android Studio باز کنید.
  2. به اولین فایل DEX پیمایش کنید. به‌عنوان مثال، classes.dex.
  3. محتوای این فایل DEX را بازرسی کنید. باید بتوانید درستی‌سنجی کنید که کلاس‌ها و روش‌های مهم تعریف‌شده در فایل «نمایه راه‌اندازی» (startup-prof.txt) در این فایل DEX اصلی وجود داشته باشند. برنامه موفق یعنی این مؤلفه‌های مهم راه‌اندازی برای بارگیری سریع‌تر اولویت‌بندی شده‌اند.

مشکلات عملکرد

این بخش برخی‌از روال‌های مطلوب را برای تعریف و محک‌زنی صحیح «نمایه‌های پایه» نشان می‌دهد تا بتوانید بیشترین بهره را از آن‌ها ببرید.

سنجه‌های راه‌اندازی را به‌درستی محک بزنید

اگر سنجه‌های راه‌اندازی شما به‌خوبی تعریف شده باشند، Baseline Profiles شما مؤثرتر خواهند بود. دو سنجه کلیدی عبارت‌اند از زمان لازم برای نمایش اولیه (TTID) و زمان لازم برای نمایش کامل (TTFD).

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

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

برای اینکه برنامه‌تان پاسخگو به‌نظر برسد، TTID و TTFD را تا حد امکان پایین نگه دارید.

سیستم می‌تواند TTID را شناسایی کند، آن را در Logcat نمایش دهد، و آن را به‌عنوان بخشی از محک‌های راه‌اندازی گزارش کند. اما سیستم نمی‌تواند TTFD را تعیین کند و مسئولیت گزارش کردن زمان رسیدن به وضعیت تعاملی کاملاً ترسیم‌شده برعهده برنامه است. می‌توانید این کار را با فراخوانی reportFullyDrawn() انجام دهید، یا اگر از Jetpack Compose استفاده می‌کنید، ReportDrawn را فراخوانی کنید. اگر چند تکلیف پس‌زمینه‌ای دارید که همه آن‌ها باید قبل‌از اینکه برنامه کاملاً ترسیم‌شده درنظر گرفته شود تکمیل شوند، می‌توانید از FullyDrawnReporter استفاده کنید، همان‌طور که در بهبود دقت زمان‌بندی راه‌اندازی شرح داده شده است.

نمایه‌های کتابخانه و نمایه‌های سفارشی

هنگام محک‌زنی تأثیر نمایه‌ها، ممکن است جدا کردن مزایای نمایه‌های برنامه‌تان از نمایه‌هایی که کتابخانه‌ها (مانند کتابخانه‌های Jetpack) ارائه می‌دهند دشوار باشد. وقتی APK خود را می‌سازید، افزایه Android Gradle هر نمایه‌ای را در وابستگی‌های کتابخانه و همچنین نمایه سفارشی شما اضافه می‌کند. این کار برای بهینه‌سازی عملکرد کلی خوب است و برای ساخت‌های نسخه پخش شما توصیه می‌شود. اما این کار اندازه‌گیری میزان بهبود عملکرد اضافی حاصل از نمایه سفارشی شما را دشوار می‌کند.

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

یک روش خودکارسازی‌شده برای مقایسه نمایه‌ها، ایجاد یک تنوع ساخت جدید است که فقط شامل نمایه‌های کتابخانه باشد و نمایه سفارشی شما را نداشته باشد. معیارهای این گونه را با گونه انتشار که هم نمایه‌های کتابخانه و هم نمایه‌های سفارشی شما را دارد مقایسه کنید. مثال زیر نشان می‌دهد که چگونه متغیری را که فقط شامل نمایه‌های کتابخانه است راه‌اندازی کنید. متغیر جدیدی به‌نام releaseWithoutCustomProfile به ماژول مصرف‌کننده نمایه‌تان اضافه کنید که معمولاً ماژول برنامه‌تان است:

کاتلین

android {
  ...
  buildTypes {
    ...
    // Release build with only library profiles.
    create("releaseWithoutCustomProfile") {
      initWith(release)
    }
    ...
  }
  ...
}
...
dependencies {
  ...
  // Remove the baselineProfile dependency.
  // baselineProfile(project(":baselineprofile"))
}

baselineProfile {
  variants {
    create("release") {
      from(project(":baselineprofile"))
    }
  }
}

شیک

android {
  ...
  buildTypes {
    ...
    // Release build with only library profiles.
    releaseWithoutCustomProfile {
      initWith(release)
    }
    ...
  }
  ...
}
...
dependencies {
  ...
  // Remove the baselineProfile dependency.
  // baselineProfile ':baselineprofile"'
}

baselineProfile {
  variants {
    release {
      from(project(":baselineprofile"))
    }
  }
}

نمونه کد قبلی وابستگی baselineProfile را از همه انواع حذف می‌کند و آن را به‌طور انتخابی فقط برای نوع release اعمال می‌کند. ممکن است به‌نظر برسد که نمایه‌های کتابخانه همچنان اضافه می‌شوند، حتی زمانی که وابستگی به ماژول تولیدکننده نمایه برداشته شده است. بااین‌حال، این واحد فقط مسئول تولید نمایه سفارشی شما است. افزایه Android Gradle هنوز برای همه گونه‌ها درحال اجرا است و مسئولیت گنجاندن نمایه‌های کتابخانه را برعهده دارد.

همچنین باید گونه جدید را به ماژول تولیدکننده نمایه اضافه کنید. در این مثال، نام واحد تولیدکننده :baselineprofile است.

کاتلین

android {
  ...
    buildTypes {
      ...
      // Release build with only library profiles.
      create("releaseWithoutCustomProfile") {}
      ...
    }
  ...
}

شیک

android {
  ...
    buildTypes {
      ...
      // Release build with only library profiles.
      releaseWithoutCustomProfile {}
      ...
    }
  ...
}

وقتی محک را از Android Studio اجرا می‌کنید، متغیر releaseWithoutCustomProfile را برای اندازه‌گیری عملکرد فقط با نمایه‌های کتابخانه انتخاب کنید، یا متغیر release را برای اندازه‌گیری عملکرد با نمایه‌های کتابخانه و سفارشی انتخاب کنید.

اجتناب از راه‌اندازی برنامه محدود به ورودی/خروجی

اگر برنامه‌تان درطول راه‌اندازی فراخوانی‌های ورودی/خروجی یا فراخوانی‌های شبکه زیادی انجام می‌دهد، این امر می‌تواند بر زمان راه‌اندازی برنامه و دقت محک‌زنی راه‌اندازی شما تأثیر منفی بگذارد. این تماس‌های سنگین می‌توانند مدت زمان نامشخصی طول بکشند که می‌تواند درطول زمان و حتی بین تکرارهای یک محک یکسان متفاوت باشد. فراخوانی‌های ورودی/خروجی معمولاً بهتر از فراخوانی‌های شبکه هستند، زیرا فراخوانی‌های شبکه ممکن است تحت‌تأثیر عوامل خارجی دستگاه و عوامل داخلی خود دستگاه قرار بگیرند. از تماس‌های شبکه درطول راه‌اندازی اجتناب کنید. در مواردی که استفاده از یکی یا دیگری اجتناب‌ناپذیر است، از I/O استفاده کنید.

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

اگر برنامه‌تان از Hilt استفاده می‌کند، می‌توانید هنگام محک‌زنی در Microbenchmark و Hilt، پیاده‌سازی‌های جعلی محدود به ورودی/خروجی ارائه دهید.

همه مسیرهای مهم کاربر را پوشش دهید

مهم است که همه مسیرهای کاربر مهم را به‌طور دقیق در تولید «نمایه پایه» خود پوشش دهید. «نمایه‌های مبنا» هیچ‌کدام از مسیرهای کاربر را که پوشش داده نشده‌اند بهبود نخواهد داد. مؤثرترین نمایه‌های خط مبنا شامل همه مسیرهای کاربر راه‌اندازی رایج و همچنین مسیرهای کاربر درون‌برنامه حساس به عملکرد مانند پیمایش فهرست‌ها است.

آزمایش آ/ب تغییرات نمایه زمان ترجمه

ازآنجایی‌که Startup Profiles و Baseline Profiles بهینه‌سازی زمان ترجمه هستند، آزمایش A/B مستقیم فایل‌های APK مختلف بااستفاده از «فروشگاه Google Play» معمولاً برای نسخه‌های تولید پشتیبانی نمی‌شود. برای ارزیابی تأثیر در محیطی شبیه به محیط تولید، رویکردهای زیر را درنظر بگیرید:

  • انتشار خارج‌از چرخه: یک انتشار خارج‌از چرخه را برای درصد کمی از پایگاه کاربرانتان بارگذاری کنید که فقط شامل تغییر نمایه باشد. این کار به شما امکان می‌دهد سنجه‌های واقعی را درباره تفاوت عملکرد جمع‌آوری کنید.

  • معیار سنجی محلی: برنامه‌تان را به‌صورت محلی با و بدون اعمال نمایه معیار سنجی کنید. بااین‌حال، توجه داشته باشید که محک‌زنی محلی بهترین سناریو را برای نمایه‌ها به شما نشان می‌دهد، زیرا تأثیرات نمایه‌های ابری از ART را که در دستگاه‌های تولید وجود دارد شامل نمی‌شود.