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
- Android Studio Hedgehog (2023.1.1) veya daha yeni bir sürüm
- Android Gradle Plugin 8.0 veya sonraki sürümler
- Jetpack makro karşılaştırmasını temel düzeyde anlama
- Android 7 (API düzeyi 24) veya sonraki sürümlere sahip fiziksel bir Android cihaz
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ç
- Android Studio'ya Hoş Geldiniz penceresinde Mevcut Bir Projeyi Aç'ı seçin.
- Klasörü
[Download Location]/codelab-android-performance/baseline-profiles
seçin.baseline-profiles
dizinini seçtiğinizden emin olun. - 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.
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.
Açılan pencerede, Şablonlar bölmesinden Referans Profil Oluşturucu'yu seçin.
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:
- Uygulamayı başlatın. Bu konu, oluşturulan sınıf tarafından kısmen ele alınmaktadır.
- İçeriğin asynkron olarak yüklenmesini bekleyin.
- Atıştırmalık listesini kaydırın.
- 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:
- Feed'deki atıştırmalık listesini bulun.
- 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:
- Atıştırmalık listesi kullanıcı arayüzü öğesini bulun.
- Hareket kenar boşluklarını, sistemde gezinmeyi tetiklemeyecek şekilde ayarlayın.
- 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:
- Atıştırmalık listesini ve kullanabileceğiniz tüm atıştırmalık öğelerini bulun.
- Listeden bir öğe seçin.
- Öğ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 tıklayın.
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.
(İ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 profillerisrc/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 bircompilationMode
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.
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.
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:
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:
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:
- Macrobenchmark ile uygulama performansını inceleme: Karşılaştırma konusunda daha ayrıntılı bilgi veren codelab.
- Performans örnekleri: Makro karşılaştırma ve diğer performans örneklerini içeren depo.
- Now In Android örnek uygulaması: Performansı artırmak için karşılaştırma özelliğini ve Temel Profilleri kullanan gerçek dünyadan bir uygulama.