Temel Profillerle uygulama performansını iyileştirin

1. Başlamadan önce

Bu codelab'de, uygulamanızın performansını optimize etmek için Temel Profilleri nasıl 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, Temel Profil oluşturma araçları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 kazançlarını doğrulayın.

Neler öğreneceksiniz?

  • Temel Profiller ve uygulamanın performansını nasıl iyileştirebilecekleri.
  • Temel Profiller nasıl oluşturulur?
  • Temel Profillerin performans kazançları.

2. Kurulum

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

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

Alternatif olarak, iki zip dosyası indirebilirsiniz:

Projeyi Android Studio'da Aç

  1. Android Studio'ya Hoş Geldiniz penceresinde 61d0a4432ef6d396.png Mevcut 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ı derlemek için app modülünü çalıştırabileceğinizden emin olun.

Örnek uygulama

Bu codelab'de JetSnack örnek uygulamasıyla çalışacaksınız. Jetpack Compose'u kullanan sanal bir atıştırmalık sipariş 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 davrandığını anlamanız gerekir. Böylece karşılaştırmalara göre kullanıcı arayüzü öğelerine erişebilirsiniz. Uygulamayı çalıştırın ve atıştırmalık sipariş ederek temel ekranlara aşinalık kazanın. Uygulamanın nasıl tasarlandığına dair ayrıntıları bilmeniz gerekmez.

23633b02ac7ce1bc.png

3. Temel Profiller nedir?

Temel Profiller, dahil edilen kod yolları için yorumlama ve tam zamanında (JIT) derleme adımlarından kaçınarak ilk lansmandan itibaren kod yürütme hızını yaklaşık% 30 artırır. Bir uygulama veya kitaplıkta Temel Profil gönderdiğinizde Android Runtime (ART), Önceden (AOT) derlemesi aracılığıyla dahil edilen kod yollarını optimize ederek her yeni kullanıcı ve her uygulama güncellemesinde performans artışı sağlayabilir. Bu profil rehberliğinde optimizasyon (PGO) sayesinde uygulamalar, çalışmayı optimize edebilir, etkileşim olumsuzluğunu azaltabilir ve son kullanıcılar için ilk lansmandan itibaren genel çalışma zamanı performansını iyileştirebilir.

Temel Profil sayesinde uygulama başlatma, ekranlar arasında gezinme veya içerikler arasında gezinme gibi tüm kullanıcı etkileşimleri, ilk kez çalıştırıldıkları andan itibaren daha sorunsuz olur. Bir uygulamanın hızını ve yanıt verme düzeyini artırdığınızda günlük etkin kullanıcı sayısı ve ortalama geri gelen ziyaret oranı yükselir.

Temel Profiller, ilk lansmandan itibaren uygulamanın çalışma zamanını iyileştiren ortak kullanıcı etkileşimleri sağlayarak optimizasyonu uygulama başlatmanın ötesinde yönlendirmeye yardımcı olur. Rehberli AOT derlemesi kullanıcı cihazlarına dayalı değildir ve mobil cihaz yerine bir geliştirme makinesinde sürüm başına bir kez yapılabilir. Sürümleri bir Temel Profil ile gönderdiğinizde uygulama optimizasyonları, tek başına Cloud Profilleri ile yapılanlara kıyasla çok daha hızlı kullanılabilir hale gelir.

Temel Profil kullanılmadığında tüm uygulama kodu, cihaz boştayken yorumlandıktan sonra JIT'in bellekte derlenir veya arka planda bir odex dosyasına dönüştürülür. Böylece kullanıcılar, bir uygulamayı yükledikten veya ilk kez güncelledikten sonra, yeni yollar optimize edilmeden önce optimum düzeyin altında bir deneyim yaşayabilir.

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

Projenize yeni bir Gradle modülü eklenmesini gerektiren bir araç test sınıfıyla Temel Profiller oluşturabilirsiniz. Bunu projenize eklemenin en kolay yolu, Android Studio Hedgehog veya sonraki sürümleriyle birlikte gelen Android Studio modül sihirbazını kullanmaktır.

Proje panelinde projenizi veya modülünüzü sağ tıklayıp Yeni > Modül.

232b04efef485e9c.png

Açılan pencerede, Şablonlar bölmesinde Temel Profil Oluşturucu'yu seçin.

b191fe07969e8c26.png

Modül adı, paket adı, dil veya derleme yapılandırma dili gibi normal parametrelerin yanı sıra, yeni modüllerde olağan olmayan iki giriş vardır: Hedef uygulama ve Gradle yönetilen cihazını kullan.

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

Gradle Yönetilen Cihazı Kullan onay kutusu, modülü otomatik olarak yönetilen Android emülatörlerinde Temel Profil oluşturma araçlarını çalıştıracak şekilde ayarlar. Gradle Yönetilen Cihazlar ile testlerinizi ölçeklendirme bölümünde Gradle Tarafından Yönetilen Cihazlar hakkında daha fazla bilgi edinebilirsiniz. Bu seçeneğin işaretini kaldırırsanız oluşturma araçları, bağlı cihazları 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 Finish'i (Son) tıklayın.

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

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

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

Bu modülde, Gradle'a bu eklentiyi uygulamanıza dahil etmemesini söyleyen com.android.test eklentisi kullanılır. Bu nedenle modül yalnızca test kodunu veya karşılaştırmaları içerebilir. Ayrıca, Temel Profillerin 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 eklentisi uygular, androidx.profileinstaller bağımlılığı ekler ve yeni oluşturulan build.gradle(.kts) modülüne baselineProfile bağımlılığı ekler:

plugins {
  id("androidx.baselineprofile")
}

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

androidx.profileinstaller bağımlılığı ekleyerek aşağıdakileri yapabilirsiniz:

  • Oluşturulan Temel Profillerin performans kazançlarını yerel olarak doğrulayın.
  • Cloud profillerini desteklemeyen Android 7 (API düzeyi 24) ve Android 8'de (API düzeyi 26) Temel Profilleri kullanın.
  • Google Play Hizmetleri'ne sahip olmayan cihazlarda Temel Profilleri kullanın.

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

Projeyi oluşturduğunuza göre artık Temel Profiller oluşturucu sınıfı yazın.

5. Temel Profil oluşturma aracı yazma

Genellikle uygulamanızın tipik kullanıcı yolculukları için Temel Profiller oluşturursunuz.

Modül sihirbazı, uygulama başlatma işleminiz için Temel Profil oluşturabilen temel bir BaselineProfileGenerator test sınıfı oluşturur ve aşağıdaki gibi görünür:

@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ıf, bir BaselineProfileRule test kuralı kullanıyor ve profil oluşturmak için bir test yöntemi içeriyor. Profili oluşturmak için giriş noktası collect() işlevidir. Yalnızca iki parametre gerektirir:

  • packageName: uygulamanızın paketi.
  • profileBlock: son lambda parametresi.

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

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

Jeneratörü özel yolculuklarla genişletin

Oluşturulan sınıfta, uygulamanızdaki ileri düzey yolculukları optimize etmek için daha fazla etkileşim yazabileceğiniz bazı TODO bulunduğunu da görebilirsiniz. Uygulama başlangıcından sonra performansı optimize edebilmeniz için bunu yapmanız önerilir.

Örnek uygulamamızda aşağıdaki işlemleri yaparak bu yolculukları tanımlayabilirsiniz:

  1. Uygulamayı başlatın. Oluşturulan sınıfın bu kapsamı zaten kısmen karşılanıyor.
  2. İçerik eşzamansız olarak yüklenene kadar bekleyin.
  3. Atıştırmalık listesini kaydırın.
  4. Atıştırmalık ayrıntılarına gidin.

Oluşturma aracını, aşağıdaki snippet'te genel yolculukları kapsayan özetlenen işlevleri içerecek şekilde 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şimleri yazın. MacrobenchmarkScope öğesinin uzantı işlevi olarak yazarak sağladığı parametre ve işlevlere erişebilirsiniz. Bu şekilde yazmak, performans kazançlarını doğrulamak için karşılaştırmalarla olan etkileşimleri yeniden kullanmanıza olanak tanır.

Eşzamansız içeriği bekleyin

Birçok uygulama, uygulama başlatılırken bir tür eşzamansız yükleme içerir. Bu, tamamen görüntüleme durumu olarak da bilinir. Bu, içeriğin ne zaman yüklenip oluşturulduğunu ve kullanıcının onunla etkileşim kurabileceğini sisteme bildirir. Oluşturucuda (waitForAsyncContent) şu etkileşimlerle durumu bekleyin:

  1. Feed'deki atıştırmalık listesini bulun.
  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

Kayan atıştırmalık listesi yolculuğunda (scrollSnackListJourney) şu etkileşimleri takip edebilirsiniz:

  1. Atıştırmalık listesi kullanıcı arayüzü öğesini bulun.
  2. Hareket kenar boşluklarını, sistemde gezinmeyi tetiklemeyecek şekilde ayarlayın.
  3. Listeyi kaydırın ve kullanıcı arayüzü düzelene kadar 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ılar yolculuğuna gidin

Son yolculukta (goToSnackDetailJourney) şu etkileşimler uygulanır:

  1. Atıştırmalık listesini ve kullanabileceğiniz tüm atıştırmalık öğelerini bulun.
  2. Listeden bir öğe seçin.
  3. Öğeyi tıklayın ve ayrıntı ekranının yüklenmesini bekleyin. Atıştırmalık listesinin artık ekranda görünmeyeceği gerçeğinden 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, çalışacağı cihazı tanımlamanız gerekir.

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

Temel Profiller oluşturmak için Gradle Yönetilen Cihaz gibi bir emülatör veya Android 13 (API 33) veya sonraki sürümleri çalıştıran bir cihaz kullanmanızı öneririz.

Süreci tekrarlanabilir hale getirmek ve Temel Profil oluşturmayı otomatik hale getirmek için Gradle Yönetilen Cihazları kullanabilirsiniz. Gradle Tarafından Yönetilen Cihazlar, manuel olarak başlatmanıza ve ortadan kaldırmanıza gerek kalmadan bir Android emülatöründe test çalıştırmanızı sağlar. Gradle Tarafından Yönetilen Cihazlar hakkında daha fazla bilgiyi Gradle Yönetilen Cihazlar ile testlerinizi ölçeklendirme bölümünde bulabilirsiniz.

Gradle Yönetilen 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'i (API düzeyi 31) kullanıyoruz ve aosp sistem görüntüsü rootlanmış erişime sahip.

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

android {
  // ...
}

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

dependencies {
  // ...
}

Ardından, Temel Profili oluşturun.

7. Temel Profili Oluşturma

Cihaz hazır olduğunda Temel Profili oluşturabilirsiniz. Baseline Profile Gradle eklentisi, oluşturucu test sınıfını çalıştırma ve oluşturulan referans profilleri uygulamanıza uygulama sürecinin tamamını otomatikleştirmek için Gradle görevleri oluşturur.

Yeni modül sihirbazı, terminal ile Android Studio arasında geçiş yapmaya gerek kalmadan Gradle görevini gerekli tüm parametrelerle hızlı bir şekilde çalıştırabilmek için ç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ından etkileşimleri birkaç kez çalıştırın ve daha sonra emülatörü kaldırıp çıktıyı Android Studio'ya gönderin.

Oluşturma aracı 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şturma aracını komut satırından çalıştırma

Alternatif olarak, oluşturucuyu komut satırından da çalıştırabilirsiniz. Gradle Yönetilen Cihaz tarafından oluşturulan görevden yararlanabilirsiniz (:app:generateBaselineProfile). Bu komut, baselineProfile(project(:baselineProfile)) bağımlılığı tarafından tanımlanan projedeki tüm testleri çalıştırır. Modül, performans kazançlarını daha sonra doğrulayacak karşılaştırmalar da içerdiğinden, bu testler başarısız olur ve bir emülatörde karşılaştırma çalıştırmaya karşı bir uyarı verir.

android
   .testInstrumentationRunnerArguments
   .androidx.benchmark.enabledRules=BaselineProfile

Bunun için tüm Temel Profil oluşturma araçlarını aşağıdaki araç ç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ı Temel Profillerle dağıtma

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

Kullanıcılar uygulamayı önceki sürümden yüklediğinde veya güncellediğinde Temel Profil de yüklenir. Böylece, uygulama ilk kez çalıştırıldığından daha iyi performans elde edilir.

Sonraki adımda, Temel Profiller kullanılarak uygulama performansının ne kadar arttığının nasıl doğrulanacağı gösterilmektedir.

8. (İsteğe bağlı) Temel Profil oluşturmayı özelleştirme

Temel Profiller Gradle Eklentisi, profillerin belirli ihtiyaçlarınızı karşılayacak şekilde nasıl oluşturulduğunu özelleştirmenizi sağlayan seçenekler içerir. Derleme komut dosyalarında baselineProfile { } yapılandırma bloğuyla davranışı değiştirebilirsiniz.

:baselineprofile modülündeki yapılandırma bloğu, managedDevices ekleme olanağı sunacak şekilde üreticilerin nasıl çalıştırılacağını belirler ve useConnectedDevices mi yoksa Gradle tarafından mı yönetilen cihazların kullanılacağına karar verir.

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

  • automaticGenerationDuringBuild: Etkinleştirilmişse üretim sürümü derlemesini oluştururken Temel Profili oluşturabilirsiniz. Bu, uygulamanızı göndermeden önce CI üzerinde geliştirme yaparken yararlıdır.
  • saveInSrc: Oluşturulan Temel Profillerin, src/ klasöründe depolanıp depolanmayacağını belirtir. Alternatif olarak, dosyaya :baselineprofile derleme klasöründen erişebilirsiniz.
  • baselineProfileOutputDir: Oluşturulan Temel Profillerin nerede depolanacağını tanımlar.
  • mergeIntoMain: Varsayılan olarak, Temel Profiller derleme varyantı (ürün türü ve derleme türü) başına oluşturulur. Tüm profilleri src/main bünyesinde birleştirmek istiyorsanız bu işareti etkinleştirerek bunu yapabilirsiniz.
  • filter: Oluşturulan Temel Profillerden hangi sınıf veya yöntemlerin dahil edileceğini ya da hariç tutulacağını filtreleyebilirsiniz. Bu, yalnızca kitaplıktaki kodun eklenmesini isteyen kitaplık geliştiricileri için yararlı olabilir.

9. Başlatma performansı iyileştirmelerini doğrulama

Temel Profili oluşturup uygulamanıza ekledikten sonra uygulamanızın performansı üzerinde istediğiniz etkiyi yarattığını doğrulayın.

Yeni modül sihirbazı StartupBenchmarks adında bir karşılaştırma sınıfı oluşturur. Rapor, uygulama başlatma süresini ölçmek için bir karşılaştırma içerir ve bunu, uygulamanın Temel Profilleri kullandığı zamanla karşılaştırır.

Sınıf aşağıdaki gibi 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
            }
        )
    }
}

Uygulamanız için karşılaştırmalar yapabilen ve performans metrikleri toplayabilen MacrobenchmarkRule kullanır. Karşılaştırma yazmak için giriş noktası, kuraldan measureRepeated işlevidir.

Birkaç parametre gerektirir:

  • Hangi uygulamanın ölçüleceğini packageName:.
  • metrics: Karşılaştırma sırasında ölçmek istediğiniz bilgi türünü belirtir.
  • iterations: Karşılaştırmanın tekrarlanma sayısı.
  • startupMode: Karşılaştırmanız başladıktan sonra başvurunuzun nasıl başlamasını istediğiniz.
  • setupBlock: Ölçümden önce uygulamanızla hangi etkileşimlerin gerçekleşmesi gerektiği.
  • measureBlock: Karşılaştırma sırasında ölçmek istediğiniz uygulamanızla etkileşimler.

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

CompilationMode

CompilationMode parametresi, uygulamanın makine koduna önceden derlenme yöntemini tanımlar. Aşağıdaki seçeneklere sahiptir:

  • DEFAULT: Varsa Temel Profilleri kullanarak uygulamayı kısmen önceden derler. Bu, herhangi bir compilationMode parametresi uygulanmamışsa kullanılır.
  • None(): Uygulama derleme durumunu sıfırlar ve uygulamayı önceden derlemez. Just-in-time derlemesi (JIT) uygulama yürütülürken hâlâ etkindir.
  • Partial(): Uygulamayı Temel Profiller veya ısınma çalıştırmaları ya da her ikisi ile önceden derler.
  • Full(): Uygulama kodunun tamamını önceden derler. Bu, Android 6 (API 23) ve önceki sürümlerde tek seçenektir.

Uygulamanızın performansını optimize etmeye başlamak istiyorsanız DEFAULT derleme modunu seçebilirsiniz, çünkü performans, uygulamanın Google Play'den yüklenmesiyle benzerdir. Temel Profillerin sağladığı performans avantajlarını karşılaştırmak istiyorsanız None ve Partial derleme modunun sonuçlarını karşılaştırarak bunu yapabilirsiniz.

İçerikleri beklemek için karşılaştırmayı değiştirme

Karşılaştırmalar, uygulamanızla etkileşime geçerek Temel Profil oluşturma araçlarına benzer şekilde yazılır. Varsayılan olarak, oluşturulan karşılaştırmalar BaselineProfileGenerator metriğine benzer şekilde yalnızca ilk karenin oluşturulmasını bekler. Bu nedenle, eşzamansız içeriği beklemek için bunu geliştirmenizi öneririz.

Oluşturma aracı için yazdığınız uzantı işlevlerini yeniden kullanarak bunu yapabilirsiniz. Bu karşılaştırma, StartupTimingMetric() kullanarak başlatma zamanlarını yakaladığından, yalnızca eşzamansız içeriği burada beklemenizi 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ırma yapma

Karşılaştırmaları, enstrümantasyonlu testleri yaptığınız gibi çalıştırabilirsiniz. Test işlevini veya yanında oluk simgesi bulunan tüm sınıfı çalıştırabilirsiniz.

587b04d1a76d1e9d.png

Android emülatörde karşılaştırma çalıştırmak, karşılaştırmanın yanlış sonuçlar verebileceğine dair bir uyarıyla çalışma zamanında başarısız olacağından fiziksel bir cihaz seçtiğinizden emin olun. Teknik olarak emülatörde çalıştırabilseniz de ana makinenizin performansını ölçersiniz. Aracınız yoğun iş yükü altındaysa karşılaştırmalarınız daha yavaş ve ters şekilde çalışır.

94e0da86b6f399d5.png

Karşılaştırmayı çalıştırdıktan sonra uygulamanız yeniden oluşturulur ve ardından karşılaştırmalarınızı çalıştırır. Karşılaştırmalar, tanımladığınız iterations metriğine göre uygulamanızı birkaç kez başlatır, durdurur, hatta yeniden yükler.

Karşılaştırmalar tamamlandıktan sonra, aşağıdaki ekran görüntüsündeki gibi Android Studio çıkışında zamanlamaları 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österilir:

timeToFirstDisplay [ms]

Süre-Tam Görüntüleme [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 bir Temel Profiliniz olduğunda yaklaşık% 28 iyileşme sağlar. Uygulama başlatılırken cihazın en fazla JIT derlemesini yapması gerektiğinden CompilationNone daha kötü performans gösteriyor. Temel Profiller AOT ile kısmi derleme, kullanıcının kullanma olasılığının en yüksek olduğu kodu derlediği ve kritik olmayan kodu önceden derlenmemiş olarak bıraktığından CompilationBaselineProfiles daha iyi performans gösterir. Bu sayede hemen yüklenmez.

10. (İsteğe bağlı) Kaydırma performansı iyileştirmesini doğrulayın

Önceki adıma benzer şekilde, kaydırma performansını ölçebilir ve doğrulayabilirsiniz. Öncelikle, karşılaştırma kuralıyla bir ScrollBenchmarks test sınıfı ve farklı derleme modları kullanan iki test yöntemi 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önteminden, gerekli parametrelerle measureRepeated işlevini kullanın. metrics parametresi için, kullanıcı arayüzü çerçeveleri oluşturmanı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 kez, yalnızca ilk düzen ve içeriği kaydırırken kare sürelerini ölçmek için setupBlock ile measureBlock arasındaki etkileşimleri daha fazla bölmeniz gerekir. Bu nedenle, varsayılan ekranı başlatan işlevleri setupBlock öğesine, daha önce oluşturulan waitForAsyncContent() ve scrollSnackListJourney() uzantı işlevlerini de measureBlock öğesine 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 karşılaştırmayı önceki gibi çalıştırabilirsiniz:

84aa99247226fc3a.png

FrameTimingMetric, 50., 90., 95. ve 99. yüzdelik dilimde kare süresini milisaniye cinsinden (frameDurationCpuMs) gösterir. Android 12 (API düzeyi 31) ve sonraki sürümlerde, karelerinizin sınırın (frameOverrunMs) ne kadar sürdüğünü de döndürür. Değer negatif olabilir. Bu, karenin oluşturulması için fazladan zaman kaldığı anlamına gelir.

Sonuçlara göre CompilationBaselineProfiles ile ortalama olarak 2 ms. daha kısa bir kare süresi elde edilir. Bu durum kullanıcılar için fark etmeyebilir. Ancak diğer yüzdelik dilimler için sonuçlar daha belirgindir. P99 için fark 43, 5 ms, yani 90 FPS'de çalışan bir cihazda 3'ten fazla atlanan karedir. Örneğin, Pixel 6'da bir kare oluşturmak için maksimum süre 1.000 ms / 90 FPS = ~11 ms'dir.

11. Tebrikler

Tebrikler, bu codelab'i başarıyla tamamladınız ve Temel Profiller ile uygulamanızın performansını iyileştirdiniz.

Ek kaynaklar

Aşağıdaki ek kaynakları inceleyin:

Referans belgeler