Temel Profillerle uygulama performansını iyileştirin

1. Başlamadan önce

Bu codelab'de, uygulamanızın performansını optimize etmek için referans profillerinin nasıl oluşturulacağı ve referans profillerinin kullanılmasının performans avantajlarının nasıl doğrulanacağı gösterilmektedir.

Gerekenler

Yapacaklarınız

  • Projeyi, temel profil oluşturucuları 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 profil oluşturma.
  • Temel profillerin performans kazanımları.

2. Hazırlanma

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 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 ç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 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ırmalardan kullanıcı arayüzü öğelerine erişebilirsiniz. Uygulamayı çalıştırın ve atıştırmalık sipariş ederek temel ekranlarla tanışın. Uygulamanın nasıl tasarlandığına dair ayrıntıları bilmeniz gerekmez.

23633b02ac7ce1bc.png

3. Taban 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. Android Runtime (ART), bir uygulamada veya kitaplıkta Temel Profil göndererek önceden derleme (AOT) aracılığıyla dahil edilen kod yollarını optimize edebilir. Böylece her yeni kullanıcı için ve her uygulama güncellemesinde performans iyileştirmeleri sağlanır. Bu profil kılavuzlu optimizasyon (PGO), uygulamaların ilk başlatmadan itibaren nihai kullanıcılar için başlangıcı optimize etmesine, etkileşimdeki takılmaları azaltmasına ve genel çalışma zamanı performansını artırmasına olanak tanır.

Referans Profili sayesinde, uygulamanın ilk kez başlatılması, ekranlar arasında gezinme veya içerikte kaydırma gibi tüm kullanıcı etkileşimleri daha sorunsuz olur. Bir uygulamanın hızını ve duyarlılığını artırmak, günlük etkin kullanıcı sayısını ve ortalama geri ziyaret oranını artırır.

Referans profilleri, uygulamanın ilk çalıştırıldığı andan itibaren uygulama çalışma süresini iyileştiren yaygın kullanıcı etkileşimleri sağlayarak uygulamanın başlatılmasının ötesinde optimizasyona rehberlik eder. Rehberli AOT derlemesi, kullanıcı cihazlarına bağlı değildir ve mobil cihaz yerine geliştirme makinesi üzerinde sürüm başına bir kez yapılabilir. Sürümleri bir referans profiliyle göndererek uygulama optimizasyonlarını yalnızca bulut profillerine göre göndermekten çok daha hızlı bir şekilde kullanıma sunabilirsiniz.

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

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

Projenize yeni bir Gradle modülünün eklenmesini gerektiren bir araçlı test sınıfıyla referans profilleri oluşturabilirsiniz. Bu modülü projenize eklemenin en kolay yolu, Android Studio Hedgehog veya sonraki sürümlerde bulunan Android Studio modül sihirbazıdı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 Referans 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 bir modül için normal olmayan iki giriş vardır: Hedef uygulama ve Gradle Managed Device'ı kullan.

Hedef uygulama, referans profilleri oluşturmak için kullanılan uygulama modülüdür. Projenizde birden fazla uygulama modülü varsa jeneratörleri çalıştırmak istediğiniz modülü seçin.

Gradle Yönetilen Cihaz'ı Kullan onay kutusu, modülü Temel Profil oluşturucuları otomatik olarak yönetilen Android emülatörlerinde çalıştıracak şekilde ayarlar. Gradle Managed Devices ile testlerinizi ölçeklendirme başlıklı makalede Gradle Managed Devices hakkında daha fazla bilgi edinebilirsiniz. Bu onay kutusunu kaldırırsanız jeneratörler bağlı olan 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 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 adlı veya sihirbazda seçtiğiniz bir Gradle modülü ekler.

Bu modül, Gradle'e bu modülü uygulamanıza dahil etmemesini söyleyen com.android.test eklentisini kullanır. Bu nedenle, yalnızca test kodu veya karşılaştırmalar içerebilir. Ayrıca, referans profillerinin otomatik olarak oluşturulmasına olanak tanıyan androidx.baselineprofile eklentisi de geçerlidir.

Sihirbaz, seçtiğiniz hedef uygulama modülünde de değişiklikler yapar. Daha açık belirtmek gerekirse, androidx.baselineprofile eklentisini uygular, androidx.profileinstaller bağımlılığını ve baselineProfile bağımlılığını yeni oluşturulan build.gradle(.kts) modülüne 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ı eklemek aşağıdakileri yapmanıza olanak tanır:

  • Oluşturulan referans profillerin performans kazançlarını yerel olarak doğrulayın.
  • Bulut profillerini desteklemeyen Android 7 (API düzeyi 24) ve Android 8 (API düzeyi 26) sürümlerinde temel profilleri kullanın.
  • Google Play Hizmetleri'nin bulunmadığı cihazlarda temel profilleri kullanın.

baselineProfile(project(":baselineprofile")) bağımlılığı, Gradle'in oluşturulan referans profillerini hangi modülden alması gerektiğini bildirir.

Projeyi ayarladığınıza göre, bir referans profili 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şlangıcı için referans profili 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, BaselineProfileRule test kuralını kullanır ve profili oluşturmak için bir test yöntemi içerir. Profili oluşturma giriş noktası collect() işlevidir. Yalnızca iki parametre gerektirir:

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

profileBlock lambda işlevinde, uygulamanızın tipik kullanıcı yolculuklarını kapsayan etkileşimleri belirtirsiniz. Kitaplık, profileBlock işlevini birkaç kez çalıştırır, çağrılan sınıfları ve işlevleri toplar ve optimize edilecek kodu içeren cihazda referans 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.

Oluşturucuyu özel yolculuklarla genişletme

Oluşturulan sınıfta, uygulamanızın ileri düzey kullanıcı yolculuklarını optimize etmek amacıyla daha fazla etkileşim yazabileceğiniz bazı TODO öğeleri de bulunduğunu görebilirsiniz. Bu işlem, uygulama başlangıcından sonra performansı optimize edebilmek için önerilir.

Örnek uygulamamızda aşağıdakileri yaparak bu yolculukları tanımlayabilirsiniz:

  1. Uygulamayı başlatın. Bu konu, oluşturulan sınıf tarafından kısmen ele alınmaktadır.
  2. İçeriğin asynkron olarak yüklenmesini 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. Sağladığı parametrelere ve işlevlere erişebilmek için MacrobenchmarkScope işlevinin uzantı işlevi olarak yazabilirsiniz. Bu şekilde yazmak, performans kazançlarını doğrulamak için karşılaştırmalarla etkileşimleri yeniden kullanmanıza olanak tanır.

Eşzamansız içeriği bekleyin

Birçok uygulama, uygulama başlatılırken tam olarak görüntülenen durum olarak da bilinen bir tür eşzamansız yükleme gerçekleştirir. Bu durum, sisteme içeriğin ne zaman yüklendiğini ve oluşturulduğunu ve kullanıcının içerikle ne zaman etkileşime geçebileceğini bildirir. Aşağıdaki etkileşimlerle jeneratördeki (waitForAsyncContent) durumun değişmesini 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ü yerleşene 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()
}

Yolculuğu ayrıntılı olarak inceleme

Son yolculuk (goToSnackDetailJourney) aşağıdaki etkileşimleri uygular:

  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. Artık ekranda 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, ç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 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ı otomatikleştirmek için Gradle Managed Devices'ı kullanabilirsiniz. Gradle tarafından yönetilen cihazlar, Android emülatörünü manuel olarak başlatmanıza ve kapatmanıza gerek kalmadan emülatörde test çalıştırmanıza olanak tanır. Gradle Managed Devices ile testlerinizi ölçeklendirme başlıklı makalede Gradle Managed Devices hakkında daha fazla bilgi edinebilirsiniz.

Gradle Managed Device'ı 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, temel profil Gradle eklentisini, tanımlanan Gradle Managed Device'ı kullanacak şekilde yapılandırın. Bunu yapmak için cihazın adını managedDevices mülküne ekleyin ve aşağıdaki snippet'te gösterildiği gibi useConnectedDevices'u devre dışı bırakın:

android {
  // ...
}

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

dependencies {
  // ...
}

Ardından, referans profilini oluşturun.

7. Temel profili oluşturma

Cihaz hazır olduğunda referans profilini 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ş yapmanıza gerek kalmadan Gradle görevini çalıştırmak için gerekli tüm parametrelerle hızlıca çalıştırabilmek amacıyla ç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örden çıkıp çıkışı Android Studio'ya sağlayın.

Oluşturucu başarıyla tamamlandıktan sonra Gradle eklentisi, oluşturulan baseline-prof.txt dosyasını src/release/generated/baselineProfile/ klasöründeki hedef uygulamanıza (:app modülü) otomatik olarak 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 Managed Device tarafından oluşturulan görevden (:app:generateBaselineProfile) yararlanabilirsiniz. Bu komut, projedeki tüm testleri baselineProfile(project(:baselineProfile)) bağımlılığı tarafından tanımlandığı şekilde çalıştırır. Modül, performans kazançlarının daha sonra doğrulanması için karşılaştırmalar da içerdiğinden bu testler, karşılaştırmaların bir emülatörde çalıştırılmasına karşı bir uyarıyla başarısız olur.

android
   .testInstrumentationRunnerArguments
   .androidx.benchmark.enabledRules=BaselineProfile

Bunun için tüm referans profil oluşturucuları aşağıdaki enstrümantasyon çalıştırıcı bağımsız değişkeniyle filtreleyebilirsiniz. Böylece 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ı referans profilleriyle dağıtma

Temel profil oluşturulduktan ve uygulamanızın kaynak koduna kopyalandıktan sonra, uygulamanızın üretim sürümünü normal şekilde derleyin. 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 Plugin tarafından seçilir ve AAB'nize veya APK'nıza dahil edilir. Sonra, derlemeyi Google Play'e yükleyin.

Kullanıcılar uygulamayı yüklediğinde veya önceki sürümden güncellediğinde referans profili de yüklenir. Bu da uygulamanın ilk çalıştırıldığında daha iyi performans göstermesine neden olur.

Sonraki adımda, referans profilleri sayesinde uygulama performansının ne kadar arttığını nasıl doğrulayacağınız 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. Bu 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 Managed cihazlar arasında seçim yapma olanağıyla jeneratörlerin nasıl çalıştırılacağını etkiler.

: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ştirilirse üretim sürümü derlemesini oluştururken referans profilini oluşturabilirsiniz. Bu, uygulamanızı dağıtmadan önce CI'de derleme yaparken faydalı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 nereye depolanacağını tanımlar.
  • mergeIntoMain: Temel profiller varsayılan olarak derleme varyantı (ürün çeşidi 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 hariç tutulacağını filtreleyebilirsiniz. Bu, yalnızca kitaplıktaki kodun dahil edilmesini isteyen kitaplık geliştiricileri için yararlı olabilir.

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

Referans profilini oluşturup uygulamanıza ekledikten sonra, uygulamanızın performansında istediğiniz etkiyi gösterip göstermediğ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çmek için bir karşılaştırma içerir ve bu süreyi uygulamanın Temel Profiller'i kullandığı zamanla 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
            }
        )
    }
}

Uygulamanız için karşılaştırmalar çalıştırıp performans metriklerini toplayabilen MacrobenchmarkRule'ü kullanır. Karşılaştırma yazmanın giriş noktası, kuraldaki 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ü.
  • iterations: Karşılaştırmanın kaç kez tekrarlanacağı.
  • 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 gerekir?
  • measureBlock: Karşılaştırma sırasında ölçmek istediğiniz uygulama etkileşimleri.

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

CompilationMode

CompilationMode parametresi, uygulamanın makine koduna nasıl önceden derlendiğini tanımlar. Aşağıdaki seçenekler sunulur:

  • DEFAULT: Varsa temel profilleri kullanarak uygulamayı kısmen önceden derleyin. Bu, herhangi bir compilationMode parametresi uygulanmazsa kullanılır.
  • None(): Uygulama derleme durumunu sıfırlar ve uygulamayı önceden derlemez. Just-in-time derleme (JIT), uygulamanın yürütülmesi sırasında etkin kalır.
  • Partial(): Uygulamayı referans profiller veya ısınma çalıştırmaları ya da her ikisi ile önceden derleyin.
  • Full(): Uygulama kodunun tamamını önceden derleyin. Android 6 (API 23) ve önceki sürümlerde tek seçenek budur.

Uygulamanızın performansını optimize etmeye başlamak istiyorsanız DEFAULT derleme modunu seçebilirsiniz. Bu modda, uygulamanın performansı Google Play'den yüklendiğindekine 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.

Karşılaştırmayı, içerik bekleyecek şekilde değiştirme

Karşılaştırmalar, uygulamanızla etkileşimleri yazarak referans profil oluşturuculara benzer şekilde yazılır. Oluşturulan karşılaştırmalar varsayılan olarak yalnızca ilk karenin oluşturulmasını bekler (BaselineProfileGenerator'ün yaptığı gibi). Bu nedenle, ayarını eşzamansız içeriği bekleyecek şekilde değiş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çeriği 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ümante testleri çalıştırdığınız şekilde çalıştırabilirsiniz. Test işlevini veya yanındaki oluk simgesini kullanarak sınıfın tamamını çalıştırabilirsiniz.

587b04d1a76d1e9d.png

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

94e0da86b6f399d5.png

Karşılaştırmayı çalıştırdığınızda uygulamanız yeniden oluşturulur ve karşılaştırmalarınızı çalıştırır. Karşılaştırmalar, tanımladığınız iterations'ye göre 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ündeki gibi Android Studio çıkışında zamanlamaları görebilirsiniz:

282f90d5f6ff5196.png

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

timeToFirstDisplay [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 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österir. 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ını ve farklı derleme modlarını kullanan iki test yöntemini 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önteminden, 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 parametresini 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çerik kaydırma sırasındaki kare sürelerini ölçmek için etkileşimleri setupBlock ve measureBlock arasında 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, karelerin süresini 50., 90., 95. ve 99. yüzdelik dilimde milisaniye cinsinden (frameDurationCpuMs) gösterir. Android 12 (API düzeyi 31) ve sonraki sürümlerde, karelerinizin sınırı ne kadar aştığını da döndürür (frameOverrunMs). Değer negatif olabilir. Bu, karenin oluşturulması için fazladan zaman kaldığını gösterir.

Sonuçlara göre, CompilationBaselineProfiles cihazın ortalama kare süresinin 2 ms. daha kısa olduğunu görebilirsiniz. Bu, kullanıcılar tarafından fark edilmeyebilir. Ancak diğer yüzdelik dilimler için sonuçlar daha belirgindir. P99 için fark 43, 5 ms'dir.Bu, 90 FPS'de çalışan bir cihazda 3'ten fazla atlanan karedir. Örneğin, Pixel 6 için bir kareyi oluşturmanın maksimum süresi 1000 ms / 90 FPS = yaklaşık 11 ms'dir.

11. Tebrikler

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

Ek kaynaklar

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

Referans dokümanları