• 29.10.2026 23:11:12
  • İbrahim Gökyar

Jetpack Compose uygulamalarında soğuk başlangıç ve ilk frame gecikmesini ölçüp azaltma rehberi. Kotlin eğitimi bağlamında profil çıkarma, baseline profile, macrobenchmark ve Play Store yayınlama için somut adımlar içerir.

Android eğitimi: Soğuk Başlangıç, AOT ve Compose First-Frame Optimizasyonu

İlk adım: Soğuk başlangıcı doğru ölçmek (Perfetto, adb ve Macrobenchmark)

Soğuk başlangıç optimizasyonuna başlamadan önce doğru ölçüm şart: Android Studio Profiler yerine Perfetto + adb ile sistem seviyesinde iz almak gerekir. Perfetto CLI ile bir trace almak için proje kökünde şu iki komutu çalıştırın:

echo "buffers: { size_kb: 32768 }
data_sources: { config { name: \"android.surfaceflinger\" } }
" > trace_config.pbtxt
perfetto -c trace_config.pbtxt -o /data/misc/perfetto-traces/trace.pb --txt
Ardından cihazdan trace.pb dosyasını çeküp Android Studio - System Trace ile açın. Bu işlem CPU, sched, binder ve GFX altındaki ilk frame gecikmesinin kaynak fonksiyonlarını (main thread blokajı, JIT kompile vs.) gösterir.

Basit, tekrarlanabilir bir ölçüm (raw) için adb ile start-time alın:

adb shell am force-stop com.example.app
adb shell am start -W -n com.example.app/.MainActivity |& tee start.txt
# start.txt içinde 'ThisTime: ' ve 'TotalTime: ' alanlarını kullanın
grep "ThisTime" start.txt
Macrobenchmark kullanarak 10 tekrarlı median değerleri almak için AndroidX Macrobenchmark testi yazın ve ./gradlew connectedAndroidTest ile çalıştırın; bu size 'önce/sonra' karşılaştırması mantığını sağlar.

Baseline profile ve PGC ile Kotlin/ART ısıtma maliyetini azaltmak

Neden baseline profile? ART, uygulama davranışını izleyip JIT veya PGO/ AOT kararları alır; runtime'da derlenen metodlar ilk yüklenmelerde ana thread'i bloke edebilir. Baseline profile ile kritik metodları önceden AOT/PGC için işaretleyip ilk çalıştırmada JIT yükünü azaltırsınız. Bu mekanizma JVM tarzı 'warming' yerine native ART düzeyinde çalışır.

Projeye profile installer ve baseline profiller eklemek için build.gradle içinde somut bağımlılık ve plugin ekleyin; ardından Macrobenchmark ile profil toplayın. Örnek Macrobenchmark kurulumuyla baseline profile üretimi:

// androidTest/kotlin/com/example/BaselineProfileGeneration.kt
@get:Rule
val benchmarkRule = androidx.benchmark.macro.MacrobenchmarkRule()

@Test
fun generateBaselineProfile() = benchmarkRule.collectBaselineProfile(packageName = "com.example.app") {
    pressHome()
    startActivityAndWait()
    // kullanıcı akışını yeniden canlandırın
    device.findObject(UiSelector().text("Giriş")).click()
}
Bu testi CI/CD veya lokal cihazda 10 tekrar çalıştırıp ortaya çıkan baseline profilleri app bundle'a dahil edin (implementation 'androidx.profileinstaller:profileinstaller:VERSION' eklenmiş olmalı).

Ölçülebilir karşılaştırma: Macrobenchmark'ta startup timing için before/after testi çalıştırın ve median 'startupTiming' veya 'firstFrameLatency' değerlerini kaydedin. Örnek metriklerin median değerlerinde %X iyileşme beklenir; burada X uygulamanın I/O ve JNI yoğunluğuna bağlıdır. Ölçümü otomatikleştirmek için CI'da ./gradlew connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.androidx.benchmark.outputDir=reports/benchmark komutunu kullanın.

Jetpack Compose + Android MVVM mimarisi: İlk frame'de ağır işleri ViewModel'e taşımak

Compose bileşenlerinde ağır senkron kod çalıştırmak ilk frame'de jank oluşturur. Teknik uygulama: ViewModel içinde viewModelScope.launch ile ön yükleme yapıp, UI tarafına StateFlow/LiveData/MutableStateFlow verisi yayınlayın. Aşağıda Compose içinde hatalı örnek (ağ çağrısı doğrudan Composable) yerine doğru yapı:

// ViewModel
class MainViewModel: ViewModel() {
  private val _uiState = MutableStateFlow(UiState.Loading)
  val uiState: StateFlow = _uiState

  init {
    viewModelScope.launch(Dispatchers.IO) {
      val data = repository.fetchStartupData() // ağ/DB
      _uiState.value = UiState.Ready(data)
    }
  }
}

// Composable
@Composable
fun HomeScreen(vm: MainViewModel = viewModel()) {
  val state by vm.uiState.collectAsState()
  when(state) { /* render */ }
}
Bu refactor, main thread blokajını azaltır çünkü ağ/DB çağrısı IO dispatcherında çalışır ve Compose sadece StateFlow değiştiğinde recomposition tetiklenir.

Edge case: ViewModel init içinde büyük bir coroutine başlattığınızda process death sonrası restore için saving gerekir. Bu durumda SavedStateHandle ile kritik küçük veriyi saklayın, ama ağır yeniden oluşturmayı (ör. büyük veri seti) cache veya local DB'den yeniden yükleme stratejisiyle yönetin. Örnek: repository.fetchFromLocalCache() hızlı dönüş, sonra arka planda ağ yenilemesi.

Renkli detaylar: Compose ilk frame için spesifik optimizasyonlar ve kod örnekleri

Compose özelinde ilk frame'i optimize etmek için şu üç somut adımı uygulayın: 1) Composition sırasında hiçbir bloklayıcı I/O yapmayın; 2) remember bloğunda ağır obje inşa etmeyin, bunun yerine rememberLazyListState veya snapshotFlow kullanın; 3) gereksiz recomposition tetikleyen State'leri ViewModel'e taşıyın. Örnek: networkImage yükleme yerine Coil ImageLoader'ı prefetch ile kullanın:

// Prefetch Coil
val imageLoader = ImageLoader(context)
LaunchedEffect(url) { imageLoader.enqueue(ImageRequest.Builder(context).data(url).build()) }
// Composable'da sadece hazır olduğunda göster
Coil, Glide veya Picasso gibi kütüphanelerle ön yükleme yaparak ilk frame'de bitmemiş bitmemiş yüklemeyi önlersiniz.

Profiling tavsiyesi: Android Studio Profiling -> System Trace ile 'first frame' sırasında hangi fonksiyonun main thread'i bloke ettiğini bulun; CPU sampling için simpleperf kullanın:

adb shell simpleperf record -p $(pidof com.example.app) -o /data/local/tmp/perf.data --duration 10
adb pull /data/local/tmp/perf.data .
simpleperf report -i perf.data
Böylece hangi fonksiyonların en çok CPU zamanını yediğini görürsünüz ve optimizasyon hedefini (ör. JSON parse, reflection-heavy kütüphane) kesinleştirmiş olursunuz.

Play Store yayınlama ve App Bundle ile başlangıç performansını korumak

Play Store yayınlama sürecinde App Bundle ve ABI split kullanmak başlangıç performansını hem iyileştirir hem de indirme boyutunu azaltır. Gradle konfigürasyonu örneği:

android {
  bundle {
    abi {
      enableSplit = true
    }
  }
}
Bu ayar uygulama paketini belirli cihazlar için küçültür; daha küçük native kütüphane seti yükleme zamanını azaltır, dolayısıyla soğuk başlangıca olumlu etkisi olur. Bundle oluşturmak için:
./gradlew bundleRelease
# çıkan .aab dosyasını bundletool ile test edebilirsiniz
bundletool build-apks --bundle=app-release.aab --output=app.apks --mode=universal

Ayrıca yayınlama öncesi R8/Proguard kurallarıyla reflection-heavy kütüphanelerin kritik metodlarını koruyun; fakat unused class stripping'i agresif tutun. Play Console'da 'Android Vitals' izleyip gerçek kullanıcılardan gelen A/B verilerini toplayın. Sonuç karşılaştırması için Play Console'daki crash/ANR ve vitals metrikleriyle macrobenchmark çıktılarınızı eşleştirin.

Sık Sorulan Sorular

Kotlin eğitimi bağlamında Jetpack Compose proje starter'ında ilk yapılması gereken optimizasyon nedir?

İlk adım ölçmek: adb shell am start -W -n com.example.app/.MainActivity ile başlangıç zamanını alın, sonra Perfetto trace ile main thread profilini çıkarın. Ardından ağır I/O'ları ViewModel'in viewModelScope.launch(Dispatchers.IO) içine taşıyın ve StateFlow ile UI'ya akım verin.

Android MVVM mimarisi kullanırken ilk frame jank'ini azaltmak için hangi somut kod değişiklikleri yapılmalı?

Ağ/DB çağrılarını Composable içinde değil ViewModel init veya özel prefetch fonksiyonlarında başlatın; Compose tarafında produceState veya collectAsState ile sadece veriyi tüketin. Örneğin repository.fetchStartupData() çağrısını viewModelScope.launch(Dispatchers.IO) içinde çağırın ve UI'ya StateFlow olarak yayınlayın.

play store yayınlama sürecinde soğuk başlangıcı etkileyen en etkili konfigürasyonlar nelerdir?

App Bundle ile ABI split aktif edin (android.bundle.abi.enableSplit = true) ve baseline profile ekleyin. Play Store'a .aab yüklemeden önce ./gradlew bundleRelease çalıştırın ve macrobenchmark ile baseline profile üreterek bundle'a dahil edin; bu kombinasyon ART AOT/PGC davranışını optimize ederek ilk frame gecikmesini azaltır.

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

📚 Bu konuyu Opendart Akademi'de öğrenin: Android Kotlin kursu · Android Kotlin eğitimi hakkında · YouTube video dersleri · Abone ol