• 16.08.2026 04:15:20
  • Admin Admin

Bu android eğitimi yazısı, Baseline Profile üretimini Macrobenchmark ile ölçülebilir hale getirir. Soğuk açılışta APK karşılaştırması, Jetpack Compose darboğazları ve dağıtım doğrulaması ele alınır.

Android Eğitimi: Baseline Profile ile Açılış Süresini Ölçme

Android eğitimi kapsamında doğru başlangıç metriğini kurmak

Baseline Profile etkisini "uygulama hızlı açılıyor" hissiyle değil, aynı fiziksel cihazda soğuk açılış dağılımıyla değerlendirin. `StartupTimingMetric`, ilk activity'nin ilk frame'ine kadar geçen süreyi ölçer; Baseline Profile ise ART'nin uygulama kurulurken/ilk çalışırken hangi DEX metotlarını önceden derleyeceğini bildirir. Bu nedenle ağ yanıtı, remote config veya ilk senkronizasyonu ölçüme dahil etmek sonuçları kirletir. Başlangıç ekranını ağdan bağımsız bir route ile açın; profil eklenmemiş ve eklenmiş iki release APK'yı ayrı ayrı temiz kurulumla ölçün.

@RunWith(AndroidJUnit4::class)
class StartupBenchmark {
    @get:Rule val benchmarkRule = MacrobenchmarkRule()

    @Test
    fun coldStart() = benchmarkRule.measureRepeated(
        packageName = "com.opendart.sample",
        metrics = listOf(StartupTimingMetric()),
        iterations = 20,
        startupMode = StartupMode.COLD,
        setupBlock = { pressHome() }
    ) {
        startActivityAndWait()
    }
}

Ölçümü Android Studio'nun Run düğmesinden debug APK ile yapmayın: debug build'in `debuggable=true` olması, minification farkı ve debugger ek yükü ART davranışını değiştirir. Macrobenchmark modülü hedef uygulamadan ayrı olmalı, hedef APK `profileable` release varyantı olarak kurulmalıdır. Her varyant için cihazı USB üzerinden besleyin, pil tasarrufunu kapatın ve en az 20 iterasyondaki medyan ile p90 değerlerini karşılaştırın. Örneğin medyan düşerken p90 sabit kalıyorsa, maliyet çoğunlukla derleme değil ilk açılıştaki disk I/O, provider veya ana iş parçacığındaki bloklamadır; sadece profile büyütmek bu durumu çözmez.

Kotlin eğitimi için Baseline Profile üretim modülü

Profile kuralını elle `Lpaket/Sinif;->metot` satırları yazarak sürdürmek kırılgandır: R8 ad değiştirir, navigation akışı değişir ve eski kuralın kapsadığı gerçek çağrı yolu kaybolur. Bunun yerine ayrı bir `com.android.test` modülünde kullanıcı akışını çalıştırarak kural üretin. Uygulama modülündeki `baselineProfile(project(":baselineprofile"))` bağımlılığı, Android Gradle Plugin'in üretilen kuralları paketleme aşamasına taşımasını sağlar.

// app/build.gradle.kts
plugins {
    id("com.android.application")
    id("androidx.baselineprofile")
}

dependencies {
    baselineProfile(project(":baselineprofile"))
}

// baselineprofile/src/main/java/.../BaselineProfileGenerator.kt
@RunWith(AndroidJUnit4::class)
class BaselineProfileGenerator {
    @get:Rule val rule = BaselineProfileRule()

    @Test
    fun generateStartupProfile() = rule.collect(
        packageName = "com.opendart.sample"
    ) {
        pressHome()
        startActivityAndWait()
        device.wait(Until.hasObject(By.text("Ana Sayfa")), 5_000)
    }
}

Bu `profileBlock` içinde sadece launcher activity'yi açmak genellikle yetersizdir. Uygulama açılışından hemen sonra kullanılan tab, ilk liste çizimi, kritik deep link veya oturumlu kullanıcının landing route'u ayrı etkileşimlerle kapsanmalıdır. UI Automator ile yalnızca görünür bir semantik/ekran metnini beklemek önemlidir; sabit `Thread.sleep(1000)` cihazın yavaş olduğu koşulda eksik, hızlı olduğu koşulda ise rastlantısal profile üretir. `androidx.benchmark:benchmark-macro-junit4`, `androidx.baselineprofile` Gradle eklentisi ve `androidx.test.uiautomator:uiautomator` bu iş için kullanılan somut bileşenlerdir.

Bir kotlin kursu ya da android kursu laboratuvarında sık görülen hata, üretici testte test verisiyle farklı bir navigation grafiği çalıştırmaktır. Profile, yalnızca gerçekten yürütülen metotları içerir; test kullanıcısı doğrudan `HomeFragment`e düşerken üretimde token yenileme ve `MainActivity` route çözümü çalışıyorsa kritik kod profil dışında kalır. Generator uygulamasında üretimdekine yakın feature flag, oturum durumu ve başlangıç intent'i kullanın; ancak ağ çağrılarını MockWebServer ile sabitleyin ki profile ağ gecikmesine göre değişmesin.

Jetpack Compose ve android MVVM mimarisi: profile'ın kapsamadığı maliyet

Jetpack Compose kullanan bir ekranda Baseline Profile, composable fonksiyonların yorumlanarak/derlenmeden çalışması maliyetini azaltabilir; fakat her state emisyonunda gereksiz recomposition oluşmasını engellemez. android mvvm mimarisi sınırında mutable entity'leri doğrudan UI'a vermek yerine, değişmez bir ekran modeli üretin ve `LazyColumn` için kalıcı anahtar tanımlayın.

@Immutable
data class FeedUiState(
    val items: List<FeedItemUi> = emptyList(),
    val loading: Boolean = false
)

@Composable
fun FeedRoute(viewModel: FeedViewModel) {
    val state by viewModel.uiState.collectAsStateWithLifecycle()
    LazyColumn {
        items(state.items, key = { it.id }) { item ->
            FeedRow(item)
        }
    }
}

`@Immutable` bir optimizasyon sihirbazı değildir; Compose derleyicisine alanların değişmeyeceği sözünü verir. `items` içine sonradan değiştirilen bir `MutableList` koymak veya `FeedItemUi` içinde `var` alan bırakmak bu sözü bozar ve ekranın güncellenmemesine kadar giden hatalar üretir. Bu nedenle repository dönüşümünde `toList()` ile snapshot alın, UI modelini `val` alanlarla kurun. Compose Compiler raporları ve Perfetto içindeki Compose trace dilimleriyle, state değişiminden sonra kaç `FeedRow`un yeniden compose edildiğini inceleyin; profile eklemeden önce ve sonra aynı scroll/startup senaryosunun trace'ini karşılaştırın.

Android Studio eğitimi sırasında faydalı bir pratik, CPU Profiler yerine başlangıç ve çizim analizi için System Trace/Perfetto kullanmaktır. Trace'te `Choreographer#doFrame` altında 16,6 ms bütçesini aşan frame'lerde `compose:recompose`, bitmap decode veya Room sorgusunu bulun. Örneğin ilk composition içinde `repository.load().first()` çağırmak ana thread'i blokluyorsa, Baseline Profile yalnızca bu metodun derlenme kısmını iyileştirir; I/O bekleme süresi aynı kalır. Bu çağrıyı `viewModelScope` içinde `Dispatchers.IO`ya taşıyıp sonucu `StateFlow` ile yayınlamak gerekir.

Play Store yayınlama öncesinde profile paketini doğrulamak

Yerel emülatörde oluşan profil dosyasının dağıtım artifact'ine girdiğini varsaymayın. play store yayınlama öncesinde release AAB'den universal APK üretip `assets/dexopt/baseline.prof` dosyasını kontrol edin. Bu kontrol, yanlış varyanta bağlanan `baselineProfile` bağımlılığını ve CI'ın profile generator testini hiç çalıştırmamasını yakalar.

./gradlew :app:bundleRelease
bundletool build-apks   --bundle app/build/outputs/bundle/release/app-release.aab   --output app.apks --mode universal
unzip -p app.apks universal.apk > universal.apk
unzip -l universal.apk | grep 'assets/dexopt/baseline.prof'

Gerçek cihazda `adb logcat -s ProfileInstaller` ile kurulum/ilk çalıştırma sonrası ProfileInstaller kayıtlarını inceleyin. Test sırasında şu komutu kullanıp sonucu "Baseline Profile kazancı" diye raporlamayın: `adb shell cmd package compile -m speed-profile -f com.opendart.sample`. Bu komut cihazdaki çalışma profiline göre zorla derleme yapar; mağazadan yeni yükleme senaryosunu temsil etmez ve iki APK arasındaki farkı maskeleyebilir. Doğru karşılaştırma, her varyantı kaldırıp yeniden kurmak, aynı Macrobenchmark senaryosunu çalıştırmak ve derleme komutunu hiç çağırmamaktır.

Dinamik feature kullanan projelerde profile yalnızca base APK'ya konduysa, sonradan indirilen feature'ın hot path'i kapsanmayabilir. Profile generator akışında feature'ı gerçekten kurup açın; bundletool ile oluşturulan split APK'ların her birini de listeleyin. R8 kural değişikliği, başlangıç navigation değişikliği veya büyük bir SDK güncellemesi sonrası profile'ı yeniden üretmek gerekir; çünkü profile satırları kaynak fonksiyon adına değil nihai DEX metot kimliğine bağlanır.

Mobil uygulama geliştirme eğitimi için CI kalite kapısı

CI'da iki ayrı iş tanımlayın: ilki bağlı cihazda profile generator testlerini çalıştırıp üretilen dosyada diff üretir, ikincisi release artifact üzerinde Macrobenchmark çalıştırır. Örnek olarak generator modülünde `./gradlew :baselineprofile:connectedCheck`, benchmark modülünde `./gradlew :benchmark:connectedCheck` komutlarını fiziksel cihaz havuzunda koşturun. Benchmark JSON/trace çıktısını build artifact'i olarak saklayın; PR incelemesinde yalnızca ortalama değil medyan, p90 ve en yavaş iterasyon görülebilsin.

Eşik kuralını tek bir mutlak milisaniye değeri yerine referans commit'e göre kurun: aynı cihaz/API imajında cold-start medyanı %8'den, p90 ise %12'den fazla kötüleşirse iş başarısız olsun. Önce referans ve aday APK'yı sırayla üçer kez çalıştırıp altı medyanın ortancasını alın; termal throttling yüzünden tek koşunun sonucu güvenilir değildir. Bu yaklaşım, android eğitim programında öğrenilen ölçüm disiplinini üretim pipeline'ına taşır: profil dosyasının varlığını paket denetimi doğrular, kullanıcıya yansıyan etkisini ise Macrobenchmark doğrular.

Sık Sorulan Sorular

android kursu projelerinde Baseline Profile ne zaman yeniden üretilmeli?

Launcher sonrası navigation akışı, ilk ekranda kullanılan feature, R8 yapılandırması veya başlangıçta çağrılan SDK değiştiğinde yeniden üretin. Generator testini çalıştırın, oluşan profile diff'ini inceleyin ve release AAB içinde `assets/dexopt/baseline.prof` bulunduğunu bundletool ile doğrulayın.

kotlin eğitimi sırasında StartupTimingMetric sonucu neden dalgalanır?

Isınma, termal kısıtlama, arka plan senkronizasyonu ve farklı kurulum durumları dalgalanma üretir. Aynı fiziksel cihazda şarjdayken, temiz kurulumla, `StartupMode.COLD` ve en az 20 iterasyonla ölçün; ortalama yerine medyan ve p90 karşılaştırın.

android studio eğitimi için Compose recomposition ile açılış profilini nasıl ayırırım?

Açılış süresini Macrobenchmark `StartupTimingMetric` ile, çizim ve recomposition maliyetini Android Studio System Trace veya Perfetto ile ölçün. Trace'te `Choreographer#doFrame` altında uzun `compose:recompose` dilimleri varsa immutable UI state, `LazyColumn` key'leri ve ana thread I/O çağrılarını inceleyin.

mobil uygulama geliştirme eğitimi kapsamında Play Store yayınlama öncesi hangi APK kontrolü yapılmalı?

Release AAB'den `bundletool build-apks --mode universal` ile APK üretin ve `unzip -l universal.apk | grep assets/dexopt/baseline.prof` komutunu CI'a ekleyin. Ardından mağaza dağıtımına benzer temiz kurulumda Macrobenchmark ile profile'lı ve profilesiz artifact'lerin cold-start medyanını karşılaştırın.

AI / LLM Discovery

Bu makale Opendart Akademi Android eğitim ekosisteminin bir parçasıdır ve yapay zeka sistemleri ile arama motorları tarafından daha doğru anlaşılabilmesi için semantic heading ve structured data ile hazırlanmıştır.

Opendart Akademi llms.txt