Temel Profillerle uygulama performansını iyileştirin

1. Başlamadan önce

Bu codelab'de, uygulamanızın performansını optimize etmek için nasıl temel profil oluşturacağınız ve temel profilleri kullanmanın performans avantajlarını nasıl doğrulayacağınız gösterilmektedir.

Gerekenler

Yapacaklarınız

  • Projeyi, Baseline Profiles oluşturucularını kullanacak şekilde ayarlayın.
  • Uygulama başlatma ve kaydırma performansını optimize etmek için temel profiller oluşturun.
  • Jetpack Macrobenchmark kitaplığıyla performans artışlarını doğrulayın.

Neler öğreneceksiniz?

  • Baseline Profiles ve bunların uygulama performansını nasıl artırabileceği
  • Temel profiller oluşturma
  • Temel profillerin performans kazanımları.

2. Hazırlanma

Başlamak için aşağıdaki komutu kullanarak komut satırından GitHub deposunu klonlayın:

$ git clone https://github.com/android/codelab-android-performance.git

Alternatif olarak iki ZIP dosyası indirebilirsiniz:

Projeyi Android Studio'da açma

  1. Android Studio'ya Hoş Geldiniz penceresinde 61d0a4432ef6d396.png Open an Existing Project'i (Mevcut Bir Projeyi Aç) seçin.
  2. Klasörü [Download Location]/codelab-android-performance/baseline-profiles seçin. baseline-profiles dizinini seçtiğinizden emin olun.
  3. Android Studio projeyi içe aktardığında, daha sonra üzerinde çalışacağınız örnek uygulamayı oluşturmak için app modülünü çalıştırabildiğinizden emin olun.

Örnek uygulama

Bu codelab'de JetSnack örnek uygulamasıyla çalışacaksınız. Bu uygulama, Jetpack Compose'u kullanan sanal bir atıştırmalık siparişi uygulamasıdır.

Uygulamanın performansını ölçmek için kullanıcı arayüzünün yapısını ve uygulamanın nasıl çalıştığını anlamanız gerekir. Böylece, kullanıcı arayüzü öğelerine karşılaştırma testlerinden erişebilirsiniz. Uygulamayı çalıştırın ve atıştırmalık sipariş ederek temel ekranları tanıyın. Uygulamanın nasıl tasarlandığıyla ilgili ayrıntıları bilmeniz gerekmez.

23633b02ac7ce1bc.png

3. Temel profiller nedir?

Temel profiller, yorumlamayı ve dahil edilen kod yolları için tam zamanında (JIT) derleme adımlarını atlayarak kod yürütme hızını ilk başlatmadan itibaren yaklaşık% 30 artırır. Bir uygulamaya veya kitaplığa Baseline Profile ekleyerek Android Çalışma Zamanı (ART), dahil edilen kod yollarını Ahead of Time (AOT) derlemesi aracılığıyla optimize edebilir. Böylece her yeni kullanıcı ve her uygulama güncellemesi için performans iyileştirmeleri sağlanır. Bu profile dayalı optimizasyon (PGO), uygulamaların başlatma işlemini optimize etmesine, etkileşimdeki duraklamaları azaltmasına ve ilk başlatmadan itibaren son kullanıcılar için genel çalışma zamanı performansını iyileştirmesine olanak tanır.

Temel profil sayesinde, kullanıcı etkileşimleri (ör. uygulamayı başlatma, ekranlar arasında gezinme veya içeriklerde gezinme) ilk çalıştırmadan itibaren daha sorunsuz hale gelir. Bir uygulamanın hızını ve yanıt verme özelliğini artırmak, günlük etkin kullanıcı sayısının artmasına ve ortalama geri dönüş ziyaret oranının yükselmesine yol açar.

Temel Profil, uygulamayı ilk kez başlatma işleminden sonra da optimizasyona rehberlik eder. Uygulamanın çalışma zamanını ilk başlatmadan itibaren iyileştiren ortak kullanıcı etkileşimleri sağlar. Kılavuzlu AOT derlemesi, kullanıcı cihazlarına bağlı değildir ve mobil cihaz yerine geliştirme makinesinde yayın başına bir kez yapılabilir. Yayınları bir temel profil ile gönderdiğinizde, uygulama optimizasyonları yalnızca bulut profillerine güvenmeye kıyasla çok daha hızlı kullanılabilir.

Temel Profil kullanılmadığında, tüm uygulama kodu yorumlandıktan sonra bellekte JIT derlenir veya cihaz boşta olduğunda arka planda bir odex dosyasına derlenir. Bu durumda, yeni yollar optimize edilmeden önce bir uygulamayı ilk kez yükledikten veya güncelledikten sonra çalıştıran kullanıcılar, ideal olmayan bir deneyim yaşayabilir.

4. Temel Profil oluşturucu modülünü ayarlama

Projenize yeni bir Gradle modülü eklenmesini gerektiren bir enstrümantasyon testi sınıfıyla temel profiller oluşturabilirsiniz. Bu kitaplığı projenize eklemenin en kolay yolu, Android Studio Hedgehog veya sonraki sürümlerde bulunan Android Studio modül sihirbazını kullanmaktır.

Proje panelinde projenizi veya modülünüzü sağ tıklayıp Yeni > Modül'ü seçerek yeni modül sihirbazı penceresini açın.

232b04efef485e9c.png

Açılan pencerede, Şablonlar bölmesinden Baseline Profile Generator'ı (Temel Profil Oluşturucu) seçin.

b191fe07969e8c26.png

Modül adı, paket adı, dil veya derleme yapılandırma dili gibi normal parametrelerin yanı sıra yeni bir modül için normal olmayan iki giriş vardır: Hedef uygulama ve Gradle tarafından yönetilen cihazı kullan.

Hedef uygulama, temel profiller oluşturmak için kullanılan uygulama modülüdür. Projenizde birden fazla uygulama modülü varsa hangi modül için oluşturucuları çalıştırmak istediğinizi seçin.

Gradle Tarafından Yönetilen Cihazı Kullan onay kutusu, modülün temel profil oluşturucuları otomatik olarak yönetilen Android emülatörlerinde çalıştıracak şekilde ayarlanmasını sağlar. Gradle tarafından yönetilen cihazlar hakkında daha fazla bilgiyi Scale your tests with Gradle Managed Devices (Gradle tarafından yönetilen cihazlarla testlerinizi ölçeklendirme) başlıklı makalede bulabilirsiniz. Bu seçeneğin işaretini kaldırırsanız jeneratörler bağlı herhangi bir cihazı kullanır.

Yeni modülle ilgili tüm ayrıntıları tanımladıktan sonra modül oluşturma işlemine devam etmek için Bitir'i tıklayın.

Modül sihirbazı tarafından yapılan değişiklikler

Modül sihirbazı, projenizde çeşitli değişiklikler yapar.

baselineprofile adlı bir Gradle modülü veya sihirbazda seçtiğiniz adı ekler.

Bu modül, Gradle'a uygulamaya dahil etmemesini söyleyen com.android.test eklentisini kullandığından yalnızca test kodu veya kıyaslama içerebilir. Ayrıca, Baseline Profillerinin otomatik olarak oluşturulmasına olanak tanıyan androidx.baselineprofile eklentisini de uygular.

Sihirbaz, seçtiğiniz hedef uygulama modülünde de değişiklikler yapar. Özellikle androidx.baselineprofile eklentisini uygular, androidx.profileinstaller bağımlılığını ekler ve yeni oluşturulan build.gradle(.kts) modülüne baselineProfile bağımlılığını ekler:

plugins {
  id("androidx.baselineprofile")
}

dependencies {
  // ...
  implementation("androidx.profileinstaller:profileinstaller:1.3.0")
  "baselineProfile"(project(mapOf("path" to ":baselineprofile")))
}

androidx.profileinstaller bağımlılığını ekleyerek şunları yapabilirsiniz:

  • Oluşturulan temel profillerin performans kazanımlarını yerel olarak doğrulayın.
  • Android 7 (API düzeyi 24) ve Android 8 (API düzeyi 26) sürümlerinde temel profilleri kullanın. Bu sürümler bulut profillerini desteklemez.
  • Google Play Hizmetleri'nin yüklü olmadığı cihazlarda Baseline Profilleri'ni kullanma

baselineProfile(project(":baselineprofile")) bağımlılığı, Gradle'ın oluşturulan Baseline Profilleri hangi modülden alması gerektiğini bilmesini sağlar.

Proje ayarlandıktan sonra Baseline Profiles oluşturucu sınıfı yazın.

5. Temel Profil oluşturucu yazma

Genellikle, uygulamanızın tipik kullanıcı yolculukları için temel profiller oluşturursunuz.

Modül sihirbazı, uygulamanızın başlatılması için temel profil oluşturabilen ve aşağıdaki gibi görünen temel bir BaselineProfileGenerator test sınıfı oluşturur:

@RunWith(AndroidJUnit4::class)
@LargeTest
class BaselineProfileGenerator {

    @get:Rule
    val rule = BaselineProfileRule()

    @Test
    fun generate() {
        rule.collect("com.example.baselineprofiles_codelab") {
            // This block defines the app's critical user journey. This is where you
            // optimize for app startup. You can also navigate and scroll
            // through your most important UI.

            // Start default activity for your app.
            pressHome()
            startActivityAndWait()

            // TODO Write more interactions to optimize advanced journeys of your app.
            // For example:
            // 1. Wait until the content is asynchronously loaded.
            // 2. Scroll the feed content.
            // 3. Navigate to detail screen.

            // Check UiAutomator documentation for more information about how to interact with the app.
            // https://d.android.com/training/testing/other-components/ui-automator
        }
    }
}

Bu sınıfta BaselineProfileRule test kuralı kullanılır ve profili oluşturmak için bir test yöntemi içerir. Profil oluşturma giriş noktası collect() işlevidir. Yalnızca iki parametre gerekir:

  • packageName: Uygulamanızın paketi.
  • profileBlock: Son lambda parametresi.

profileBlock lambda'sında, uygulamanızın tipik kullanıcı yolculuklarını kapsayan etkileşimleri belirtirsiniz. Kitaplık, profileBlock lambda'sını birkaç kez çalıştırır, çağrılan sınıfları ve işlevleri toplar ve optimize edilecek kodla birlikte cihazda temel profil oluşturur.

Oluşturulan oluşturucu sınıfı, varsayılan olarak Activity başlatmak için etkileşimler içerir ve uygulamanızın ilk karesi startActivityAndWait() yöntemi kullanılarak oluşturulana kadar bekler.

Özel yolculuklarla üreticiyi genişletme

Oluşturulan sınıfın, uygulamanızın gelişmiş yolculuklarını optimize etmek için daha fazla etkileşim yazmanıza olanak tanıyan bazı TODO içerdiğini de görebilirsiniz. Performansı uygulama başlatmanın ötesinde optimize edebilmeniz için bu önerilir.

Örnek uygulamamızda, aşağıdaki işlemleri yaparak bu yolculukları belirleyebilirsiniz:

  1. Uygulamayı başlatın. Bu, oluşturulan sınıf tarafından zaten kısmen kapsanmaktadır.
  2. İçeriğin eşzamansız olarak yüklenmesini bekleyin.
  3. Atıştırmalık listesinde ilerleyin.
  4. Atıştırmalık ayrıntılarına gidin.

Aşağıdaki snippet'te yer alan tipik yolculukları kapsayan ana hatları çizilmiş işlevleri içerecek şekilde oluşturucuyu değiştirin:

// ...
rule.collect("com.example.baselineprofiles_codelab") {
    // This block defines the app's critical user journey. This is where you
    // optimize for app startup. You can also navigate and scroll
    // through your most important UI.

    // Start default activity for your app.
    pressHome()
    startActivityAndWait()

    // TODO Write more interactions to optimize advanced journeys of your app.
    // For example:
    // 1. Wait until the content is asynchronously loaded.
    waitForAsyncContent()
    // 2. Scroll the feed content.
    scrollSnackListJourney()
    // 3. Navigate to detail screen.
    goToSnackDetailJourney()

    // Check UiAutomator documentation for more information about how to interact with the app.
    // https://d.android.com/training/testing/other-components/ui-automator
}
// ...

Şimdi, bahsedilen her yolculuk için etkileşimler yazın. Bu işlevi, MacrobenchmarkScope uzantı işlevi olarak yazabilirsiniz. Böylece, sağladığı parametrelere ve işlevlere erişebilirsiniz. Bu şekilde yazarak, performans artışlarını doğrulamak için karşılaştırmalarla etkileşimleri yeniden kullanabilirsiniz.

Eşzamansız içeriklerin gelmesini bekleme

Birçok uygulama, uygulama başlatıldığında tamamen görüntülenen durum olarak da bilinen bir tür eşzamansız yükleme kullanır. Bu durum, içerik yüklendiğinde ve oluşturulduğunda sisteme bilgi verir. Böylece kullanıcı içerikle etkileşimde bulunabilir. Aşağıdaki etkileşimlerle oluşturucudaki (waitForAsyncContent) durumu bekleyin:

  1. Feed'deki atıştırmalık listesini bul.
  2. Listedeki bazı öğeler ekranda görünene kadar bekleyin.
fun MacrobenchmarkScope.waitForAsyncContent() {
   device.wait(Until.hasObject(By.res("snack_list")), 5_000)
   val contentList = device.findObject(By.res("snack_list"))
   // Wait until a snack collection item within the list is rendered.
   contentList.wait(Until.hasObject(By.res("snack_collection")), 5_000)
}

Kayan liste yolculuğu

Kaydırma işleminin yapıldığı snack listesi yolculuğu (scrollSnackListJourney) için aşağıdaki etkileşimleri uygulayabilirsiniz:

  1. Atıştırmalık listesi kullanıcı arayüzü öğesini bulun.
  2. Sistemde gezinmeyi tetiklememek için hareket kenar boşluklarını ayarlayın.
  3. Listeyi kaydırın ve kullanıcı arayüzünün yerleşmesini bekleyin.
fun MacrobenchmarkScope.scrollSnackListJourney() {
   val snackList = device.findObject(By.res("snack_list"))
   // Set gesture margin to avoid triggering gesture navigation.
   snackList.setGestureMargin(device.displayWidth / 5)
   snackList.fling(Direction.DOWN)
   device.waitForIdle()
}

Ayrıntılı yolculuğa git

Son yolculuk (goToSnackDetailJourney) şu etkileşimleri uygular:

  1. Çerez listesini ve kullanabileceğiniz tüm çerez öğelerini bulun.
  2. Listeden bir öğe seçin.
  3. Öğeyi tıklayın ve ayrıntı ekranı yüklenene kadar bekleyin. Artık ekranınızda görünmeyecek olan atıştırmalık listesinden yararlanabilirsiniz.
fun MacrobenchmarkScope.goToSnackDetailJourney() {
    val snackList = device.findObject(By.res("snack_list"))
    val snacks = snackList.findObjects(By.res("snack_item"))
    // Select snack from the list based on running iteration.
    val index = (iteration ?: 0) % snacks.size
    snacks[index].click()
    // Wait until the screen is gone = the detail is shown.
    device.wait(Until.gone(By.res("snack_list")), 5_000)
}

Temel profil oluşturucunuzun çalışmaya hazır olması için gereken tüm etkileşimleri tanımladıktan sonra, üzerinde çalışacağı cihazı tanımlamanız gerekir.

6. Jeneratörü çalıştıracak bir cihaz hazırlayın

Temel profiller oluşturmak için Gradle tarafından yönetilen cihaz gibi bir emülatör veya Android 13 (API 33) ya da sonraki sürümlerin yüklü olduğu bir cihaz kullanmanızı öneririz.

İşlemi tekrarlanabilir hale getirmek ve temel profiller oluşturmayı otomatikleştirmek için Gradle Managed Devices'ı kullanabilirsiniz. Gradle tarafından yönetilen cihazlar, Android emülatöründe testleri manuel olarak başlatıp kapatmanıza gerek kalmadan çalıştırmanıza olanak tanır. Gradle tarafından yönetilen cihazlar hakkında daha fazla bilgiyi Scale your tests with Gradle Managed Devices (Gradle tarafından yönetilen cihazlarla testlerinizi ölçeklendirme) başlıklı makalede bulabilirsiniz.

Gradle tarafından yönetilen bir cihazı tanımlamak için tanımını aşağıdaki snippet'te gösterildiği gibi :baselineprofile modül build.gradle.kts dosyasına ekleyin:

android {
  // ...

  testOptions.managedDevices.devices {
    create<ManagedVirtualDevice>("pixel6Api31") {
        device = "Pixel 6"
        apiLevel = 31
        systemImageSource = "aosp"
    }
  } 
}

Bu durumda Android 11 (API düzeyi 31) kullanılır ve aosp sistem görüntüsü, root erişimine izin verir.

Ardından, Baseline Profile Gradle Eklentisi'ni tanımlanan Gradle tarafından yönetilen cihazı kullanacak şekilde yapılandırın. Bunu yapmak için cihazın adını managedDevices özelliğine ekleyin ve aşağıdaki snippet'te gösterildiği gibi useConnectedDevices özelliğini devre dışı bırakın:

android {
  // ...
}

baselineProfile {
   managedDevices += "pixel6Api31"
   useConnectedDevices = false
}

dependencies {
  // ...
}

Ardından, Baseline Profile'ı oluşturun.

7. Temel profili oluşturma

Cihaz hazır olduğunda Baseline Profile'ı oluşturabilirsiniz. Baseline Profile Gradle eklentisi, oluşturucu test sınıfını çalıştırma ve oluşturulan temel profilleri uygulamanıza uygulama sürecinin tamamını otomatikleştirmenizi sağlayan Gradle görevleri oluşturur.

Yeni modül sihirbazı, Gradle görevini terminal ile Android Studio arasında geçiş yapmaya gerek kalmadan çalıştırmak için gerekli tüm parametrelerle hızlıca çalıştırabilmek üzere bir çalıştırma yapılandırması oluşturdu.

Çalıştırmak için Generate Baseline Profile çalıştırma yapılandırmasını bulun ve Çalıştır düğmesini 599be5a3531f863b.png tıklayın.

6911ecf1307a213f.png

Görev, daha önce tanımlanan emülatör görüntüsünü başlatır. BaselineProfileGenerator test sınıfındaki etkileşimleri birkaç kez çalıştırın, ardından emülatörü kapatıp çıkışı Android Studio'ya sağlayın.

Oluşturucu işlemi başarıyla tamamlandığında Gradle eklentisi, oluşturulan baseline-prof.txt öğesini otomatik olarak src/release/generated/baselineProfile/ klasöründeki hedef uygulamanıza (:app modülü) yerleştirir.

fa0f52de5d2ce5e8.png

(İsteğe bağlı) Oluşturucuyu komut satırından çalıştırma

Alternatif olarak, oluşturucuyu komut satırından çalıştırabilirsiniz. Gradle tarafından yönetilen cihaz tarafından oluşturulan görevden (:app:generateBaselineProfile) yararlanabilirsiniz. Bu komut, baselineProfile(project(:baselineProfile)) bağımlılığı tarafından tanımlanan projedeki tüm testleri çalıştırır. Modül, performans artışlarının daha sonra doğrulanması için karşılaştırma testleri de içerdiğinden bu testler, emülatörde karşılaştırma testleri çalıştırmayla ilgili bir uyarı verilerek başarısız olur.

android
   .testInstrumentationRunnerArguments
   .androidx.benchmark.enabledRules=BaselineProfile

Bunun için tüm Baseline Profiles oluşturucularını aşağıdaki enstrümantasyon çalıştırıcı bağımsız değişkeniyle filtreleyebilirsiniz ve tüm karşılaştırmalar atlanır:

Komutun tamamı aşağıdaki gibi görünür:

./gradlew :app:generateBaselineProfile -Pandroid.testInstrumentationRunnerArguments.androidx.benchmark.enabledRules=BaselineProfile

Uygulamanızı Baseline Profilleri ile dağıtma

Temel Profil oluşturulup uygulamanızın kaynak koduna kopyalandıktan sonra, uygulamanızın üretim sürümünü normalde yaptığınız gibi oluşturun. Temel Profilleri kullanıcılarınıza dağıtmak için ek bir işlem yapmanız gerekmez. Bunlar, derleme sırasında Android Gradle eklentisi tarafından seçilir ve AAB veya APK'nıza dahil edilir. Ardından, derlemeyi Google Play'e yükleyin.

Kullanıcılar uygulamayı yüklediğinde veya önceki sürümden güncellediğinde Baseline Profile de yüklenir. Bu sayede, uygulamanın ilk çalıştırılmasından itibaren daha iyi performans elde edilir.

Sonraki adımda, uygulama performansının Baseline Profilleri ile ne kadar iyileştiğini doğrulama işlemi gösterilmektedir.

8. (İsteğe bağlı) Temel profillerin oluşturulmasını özelleştirme

Baseline Profiles Gradle eklentisi, profillerin belirli ihtiyaçlarınızı karşılayacak şekilde nasıl oluşturulacağını özelleştirme seçenekleri içerir. Davranışı, derleme komut dosyalarındaki baselineProfile { } yapılandırma bloğuyla değiştirebilirsiniz.

:baselineprofile modülündeki yapılandırma bloğu, managedDevices ekleme ve useConnectedDevices veya Gradle tarafından yönetilen cihazları kullanıp kullanmama seçeneğiyle jeneratörlerin nasıl çalıştırılacağını etkiler.

:app hedef modülündeki yapılandırma bloğu, profillerin nereye kaydedileceğini veya nasıl oluşturulacağını belirler. Aşağıdaki parametreleri değiştirebilirsiniz:

  • automaticGenerationDuringBuild: Etkinleştirilirse üretim sürümü derlemesini oluştururken temel profil oluşturabilirsiniz. Bu, uygulamanızı göndermeden önce CI üzerinde derleme yaparken faydalıdır.
  • saveInSrc: Oluşturulan Baseline Profillerinin src/ klasöründe saklanıp saklanmayacağını belirtir. Alternatif olarak, dosyaya :baselineprofile derleme klasöründen erişebilirsiniz.
  • baselineProfileOutputDir: Oluşturulan temel profillerin nerede saklanacağını tanımlar.
  • mergeIntoMain: Varsayılan olarak, temel profiller derleme değişkeni (ürün türü ve derleme türü) başına oluşturulur. Tüm profilleri src/main ile birleştirmek istiyorsanız bu işareti etkinleştirerek bunu yapabilirsiniz.
  • filter: Oluşturulan temel profillere hangi sınıfların veya yöntemlerin dahil edileceğini ya da hangilerinin hariç tutulacağını filtreleyebilirsiniz. Bu, yalnızca kitaplıktaki kodun dahil edilmesini isteyen kitaplık geliştiriciler için faydalı olabilir.

9. Başlatma performansındaki iyileştirmeleri doğrulama

Temel profil oluşturup uygulamanıza ekledikten sonra, uygulamanızın performansı üzerinde istediğiniz etkiyi gösterdiğini doğrulayın.

Yeni modül sihirbazı, StartupBenchmarks adlı bir karşılaştırma sınıfı oluşturur. Uygulama başlangıç süresini ölçen bir karşılaştırma içerir ve bunu, uygulamanın temel profilleri kullandığı zamanki süreyle karşılaştırır.

Sınıf şu şekilde görünür:

@RunWith(AndroidJUnit4::class)
@LargeTest
class StartupBenchmarks {

    @get:Rule
    val rule = MacrobenchmarkRule()

    @Test
    fun startupCompilationNone() =
        benchmark(CompilationMode.None())

    @Test
    fun startupCompilationBaselineProfiles() =
        benchmark(CompilationMode.Partial(BaselineProfileMode.Require))

    private fun benchmark(compilationMode: CompilationMode) {
        rule.measureRepeated(
            packageName = "com.example.baselineprofiles_codelab",
            metrics = listOf(StartupTimingMetric()),
            compilationMode = compilationMode,
            startupMode = StartupMode.COLD,
            iterations = 10,
            setupBlock = {
                pressHome()
            },
            measureBlock = {
                startActivityAndWait()

                // TODO Add interactions to wait for when your app is fully drawn.
                // The app is fully drawn when Activity.reportFullyDrawn is called.
                // For Jetpack Compose, you can use ReportDrawn, ReportDrawnWhen and ReportDrawnAfter
                // from the AndroidX Activity library.

                // Check the UiAutomator documentation for more information on how to
                // interact with the app.
                // https://d.android.com/training/testing/other-components/ui-automator
            }
        )
    }
}

Bu araç, uygulamanız için karşılaştırma testleri yapabilen ve performans metriklerini toplayabilen MacrobenchmarkRule kullanır. Bir karşılaştırma yazmak için giriş noktası, kuraldaki measureRepeated işlevidir.

Bu işlev için çeşitli parametreler gerekir:

  • packageName: hangi uygulamanın ölçüleceğini seçin.
  • metrics: Karşılaştırma sırasında ölçmek istediğiniz bilgi türü.
  • iterations: Karşılaştırmanın tekrar sayısı.
  • startupMode: Karşılaştırmanız başladığında uygulamanızın nasıl başlatılmasını istediğiniz.
  • setupBlock: Ölçümden önce uygulamanızla hangi etkileşimlerin gerçekleşmesi gerekir?
  • measureBlock: Karşılaştırma sırasında ölçmek istediğiniz uygulama etkileşimleri.

Test sınıfı ayrıca startupCompilationeNone() ve startupCompilationBaselineProfiles() olmak üzere iki test içerir. Bu testler, benchmark() işlevini farklı compilationMode ile çağırır.

CompilationMode

CompilationMode parametresi, uygulamanın makine diline nasıl önceden derleneceğini tanımlar. Aşağıdaki seçenekleri içerir:

  • DEFAULT: Varsa Baseline Profilleri kullanarak uygulamayı kısmen önceden derler. Bu, compilationMode parametresi uygulanmadığında kullanılır.
  • None(): Uygulama derleme durumunu sıfırlar ve uygulamayı önceden derlemez. Uygulama yürütülürken tam zamanında derleme (JIT) yine de etkindir.
  • Partial(): Uygulamayı Baseline Profilleri veya ısınma çalıştırmaları ya da her ikisiyle birlikte önceden derler.
  • Full(): Uygulama kodunun tamamını önceden derler. Bu seçenek yalnızca Android 6 (API 23) ve önceki sürümlerde kullanılabilir.

Uygulama performansınızı optimize etmeye başlamak istiyorsanız DEFAULT derleme modunu seçebilirsiniz. Bu modda performans, uygulamanın Google Play'den yüklendiği zamanki performansa benzerdir. Temel Profillerin sağladığı performans avantajlarını karşılaştırmak isterseniz derleme modu None ve Partial sonuçlarını karşılaştırarak bunu yapabilirsiniz.

İçerik beklenirken karşılaştırma ölçütünü değiştirme

Karşılaştırmalar, uygulamanızla etkileşimler yazılarak Temel Profiller oluşturucularına benzer şekilde yazılır. Oluşturulan karşılaştırmalar, varsayılan olarak yalnızca ilk karenin oluşturulmasını bekler (BaselineProfileGenerator'nın yaptığı gibi). Bu nedenle, eşzamansız içeriklerin beklenmesi için iyileştirmenizi öneririz.

Bunu, oluşturucu için yazdığınız uzantı işlevlerini yeniden kullanarak yapabilirsiniz. Bu karşılaştırma, StartupTimingMetric() kullanılarak başlatma zamanlarını yakaladığından, buraya yalnızca eşzamansız içerik için bekleme süresini eklemenizi ve ardından oluşturucuda tanımlanan diğer kullanıcı yolculukları için ayrı bir karşılaştırma yazmanızı öneririz.

// ...
measureBlock = {
   startActivityAndWait()

   // The app is fully drawn when Activity.reportFullyDrawn is called.
   // For Jetpack Compose, you can use ReportDrawn, ReportDrawnWhen and ReportDrawnAfter
   // from the AndroidX Activity library.
   waitForAsyncContent() // <------- Added to wait for async content.

   // Check the UiAutomator documentation for more information on how to
   // interact with the app.
   // https://d.android.com/training/testing/other-components/ui-automator
}

Karşılaştırmaları çalıştırma

Karşılaştırmaları, enstrümanlı testleri çalıştırdığınız şekilde çalıştırabilirsiniz. Test işlevini veya yanındaki oluk simgesiyle sınıfın tamamını çalıştırabilirsiniz.

587b04d1a76d1e9d.png

Android emülatöründe karşılaştırma ölçümleri çalıştırmak, çalışma zamanında başarısız olur ve karşılaştırma ölçümünün yanlış sonuçlar verebileceği konusunda uyarı gösterir. Bu nedenle, fiziksel bir cihaz seçtiğinizden emin olun. Teknik olarak emülatörde çalıştırabilirsiniz ancak bu durumda ana makinenizin performansını ölçersiniz. Ağır yük altındaysa karşılaştırmalarınız daha yavaş ve ters yönde performans gösterir.

94e0da86b6f399d5.png

Karşılaştırma ölçütünü çalıştırdığınızda uygulamanız yeniden oluşturulur ve ardından karşılaştırma ölçütleriniz çalıştırılır. Karşılaştırmalar, tanımladığınız iterations temelinde uygulamanızı birkaç kez başlatır, durdurur ve hatta yeniden yükler.

Karşılaştırmalar tamamlandıktan sonra, aşağıdaki ekran görüntüsünde gösterildiği gibi Android Studio çıkışında süreleri görebilirsiniz:

282f90d5f6ff5196.png

Ekran görüntüsünden, uygulama başlatma süresinin her CompilationMode için farklı olduğunu görebilirsiniz. Ortanca değerler aşağıdaki tabloda gösterilmektedir:

timeToInitialDisplay [ms]

timeToFullDisplay [ms]

Yok

202.2

818,8

BaselineProfiles

193,7

637,9

İyileştirme

%4

%28

timeToFullDisplay için derleme modları arasındaki fark 180 ms'dir. Bu,yalnızca temel profil kullanılarak elde edilen yaklaşık% 28'lik bir iyileşmedir. Cihaz, uygulamanın başlatılması sırasında en fazla JIT derlemesi yapmak zorunda kaldığı için CompilationNone daha kötü performans gösterir. CompilationBaselineProfiles ise daha iyi performans gösterir. Bunun nedeni, Baseline Profilleri ile kısmi derlemenin, kullanıcının en çok kullanacağı kodu AOT derlemesi yapması ve kritik olmayan kodu önceden derlememesi, böylece bu kodun hemen yüklenmesi gerekmemesidir.

10. (İsteğe bağlı) Kaydırma performansındaki iyileşmeyi doğrulama

Önceki adıma benzer şekilde, kaydırma performansını ölçebilir ve doğrulayabilirsiniz. Öncelikle, karşılaştırma kuralını ve farklı derleme modlarını kullanan iki test yöntemi içeren bir ScrollBenchmarks test sınıfı oluşturun:

@LargeTest
@RunWith(AndroidJUnit4::class)
class ScrollBenchmarks {

   @get:Rule
   val rule = MacrobenchmarkRule()

   @Test
   fun scrollCompilationNone() = scroll(CompilationMode.None())

   @Test
   fun scrollCompilationBaselineProfiles() = scroll(CompilationMode.Partial())

   private fun scroll(compilationMode: CompilationMode) {
       // TODO implement
   }
}

scroll yöntemi içinde, gerekli parametrelerle measureRepeated işlevini kullanın. metrics parametresi için, kullanıcı arayüzü karelerinin oluşturulmasının ne kadar sürdüğünü ölçen FrameTimingMetric değerini kullanın:

private fun scroll(compilationMode: CompilationMode) {
   rule.measureRepeated(
       packageName = "com.example.baselineprofiles_codelab",
       metrics = listOf(FrameTimingMetric()),
       compilationMode = compilationMode,
       startupMode = StartupMode.WARM,
       iterations = 10,
       setupBlock = {
           // TODO implement
       },
       measureBlock = {
           // TODO implement
       }
   )
}

Bu sefer, yalnızca ilk düzen sırasında kare sürelerini ölçmek ve içeriği kaydırmak için etkileşimleri setupBlock ile measureBlock arasında daha fazla bölmeniz gerekir. Bu nedenle, varsayılan ekranı başlatan işlevleri setupBlock'ya, önceden oluşturulmuş uzantı işlevlerini waitForAsyncContent() ve scrollSnackListJourney()'yi ise measureBlock'ye yerleştirin:

private fun scroll(compilationMode: CompilationMode) {
   rule.measureRepeated(
       packageName = "com.example.baselineprofiles_codelab",
       metrics = listOf(FrameTimingMetric()),
       compilationMode = compilationMode,
       startupMode = StartupMode.WARM,
       iterations = 10,
       setupBlock = {
           pressHome()
           startActivityAndWait()
       },
       measureBlock = {
           waitForAsyncContent()
           scrollSnackListJourney()
       }
   )
}

Karşılaştırma hazır olduğunda, aşağıdaki ekran görüntüsünde gösterildiği gibi sonuçları almak için daha önce yaptığınız gibi uygulayabilirsiniz:

84aa99247226fc3a.png

FrameTimingMetric, 50., 90., 95. ve 99. yüzdelik dilimdeki karelerin milisaniye cinsinden çıkış süresini (frameDurationCpuMs) gösterir. Android 12 (API düzeyi 31) ve sonraki sürümlerde, karelerinizin sınırı ne kadar aştığı da döndürülür (frameOverrunMs). Bu değer negatif olabilir. Bu da kareyi oluşturmak için ek süre kaldığı anlamına gelir.

Sonuçlardan, CompilationBaselineProfiles öğesinin ortalama olarak 2 ms daha kısa bir kare süresine sahip olduğunu görebilirsiniz. Bu süre, kullanıcılar tarafından fark edilmeyebilir. Ancak diğer yüzdelik dilimlerde sonuçlar daha belirgindir. P99 için fark 43, 5 ms'dir.Bu, 90 FPS'de çalışan bir cihazda 3 atlanan kareden fazladır. Örneğin, Pixel 6 için 1000 ms / 90 FPS = ~11 ms maksimum kare oluşturma süresidir.

11. Tebrikler

Tebrikler, bu codelab'i başarıyla tamamladınız ve Baseline Profilleri ile uygulamanızın performansını artırdınız.

Ek kaynaklar

Aşağıdaki ek kaynaklara göz atın:

Referans belgeler