Gecikme, mobil uygulamada kullanıcı eylemi ile arayüz tepkisi arasında, ana iş parçacığının aşırı yüklenmesi, bellek sızıntıları veya optimize edilmemiş G/Ç işlemleri nedeniyle oluşan fark edilir bir gecikmedir. Mantıksal hatalarla ilgili aksaklıkların aksine, gecikme bir performans sorunudur: uygulama doğru çalışır ancak yavaştır. AppDynamics Mobile App Performance Report 2024'e göre, kullanıcıların %62'si bir uygulama 3 saniyeden fazla gecikirse onu siler. Gecikmeyi teşhis etmek, Android Studio Profiler ve Xcode Instruments ile CPU, bellek ve ağ profillemesi gerektirir.
Önemli Noktalar
Gecikme, mobil uygulamada kullanıcı eylemi (dokunma, kaydırma, metin girişi) ile arayüz yanıtı arasında öznel olarak fark edilebilir bir gecikmedir. Teknik olarak, gecikme giriş olayı ile tam kare işleme arasındaki süre olarak ölçülür: rahat eşik 100 ms'ye kadar, fark edilebilir 200 ms'den itibaren, kritik 500 ms'nin üzerindedir.
Kullanıcı terminolojisinde “gecikme” ve “yavaşlama” sıklıkla eşanlamlı kullanılır, ancak teknik olarak gecikme sabit bir gecikmedir (ör. her dokunuşta 300 ms), “yavaşlama” ise aralıklı bir yavaşlamadır: uygulama akıcı çalışır ve ardından bir saniye donar. Aksaklık, gecikmenin aksine, hızla değil görüntüleme doğruluğuyla ilgilidir.
Google Play ve App Store, uygulamaları sıralarken performans metriklerini dikkate alır. ANR oranı, takılma sıklığı ve başlangıç süresi, arama görünürlüğünü ve yükleme dönüşümünü etkiler. Sürekli gecikmesi olan bir uygulama, ilk başlatmadan sonra kullanıcıların %40'ına kadarını kaybeder.
Gecikme, ana UI iş parçacığı kareleri 60 FPS (kare başına 16,6 ms) veya 120 FPS (8,3 ms) hızında işleyemediğinde oluşur. Gecikmelerin ana kaynaklarını inceleyelim.
UI iş parçacığındaki herhangi bir senkron işlem — SharedPreferences'tan okuma, suspend olmadan Room aracılığıyla veritabanıyla çalışma, bir görüntüyü Bitmap'e kod çözme — kare işlemeyi bloke eder. Android'de bu takılmaya neden olur, iOS'ta Core Animation işlemesinde gecikmeye neden olur.
Android'de Çöp Toplayıcı veya iOS'ta ARC bellek boşaltma işlemi yaptığında, tüm iş parçacıkları duraklatılır. Sık GC duraklamaları, çok sayıda geçici nesne oluşturulduğunda meydana gelir — örneğin, her bağdaştırıcı çağrısında yeni bir ViewHolder örneği oluşturmak. Bu, sarsak kaydırma olarak kendini gösterir.
İç içe ConstraintLayout, birden çok LinearLayout, örtüşen View'ler — her iç içe geçme seviyesi ölçüm ve layout pass süresini artırır. Xcode, derin katman hiyerarşisinin (10 seviyeden fazla) FPS'de %20-30 düşüşe neden olduğunu belirtir.
Gecikme nedenlerini belirlemek için IDE'lere yerleşik profilleyiciler ve sistem izleme araçları kullanılır. Her araç kendi görevini çözer.
CPU Profiler, hangi yöntemlerin CPU süresi tükettiğini ve hangi iş parçacıklarında yürütüldüklerini gösterir. Ağır hesaplama yapan bir yöntem ana iş parçacığında çalışıyorsa — bu temel nedendir. Örnek Java Metodu etkinleştirilerek iz kaydı, herhangi bir anda çağrı yığınını görmeyi ve sıcak noktaları bulmayı sağlar.
iOS için eşdeğer araç — Time Profiler — her milisaniyede yığın örnekleri toplar ve her yöntemin CPU süresinin yüzde kaçını tükettiğini gösterir. Main Thread Only bayrağıyla birleştirildiğinde, yalnızca ana iş parçacığı işlemlerini filtreleyerek doğrudan gecikme kaynaklarını işaret eder.
Yavaş ağ istekleri, UI iş parçacığı bloke olmasa bile gecikme izlenimi yaratır. Android Studio'da Network Profiler ve Xcode'da Network Link Conditioner, yavaş bağlantıları simüle etmeye ve uygulamanın gerçek koşullarda nasıl davrandığını belirlemeye olanak tanır. İlerleme olmadan parçalı yanıtlar ve büyük JSON yükleri, görünür gecikmenin tipik kaynaklarıdır.
Zaman ölçümlü OkHttp ile ağ isteği profilleme örneği:
class TimingInterceptor : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val start = System.nanoTime()
val response = chain.proceed(chain.request())
val duration = (System.nanoTime() - start) / 1_000_000
Log.d("Timing", "Request took $duration ms")
return response
}
}
Gecikmeyi gidermek sistematik çalışma gerektirir: tek bir yöntemi optimize etmekten mimari değişikliklere kadar. En etkili teknikleri inceleyelim.
Ağ istekleri için Dispatchers.IO ve hesaplamalar için Dispatchers.Default ile Kotlin Coroutines, ana iş parçacığının UI için boş kalmasını sağlar. iOS'ta Grand Central Dispatch, arka plan görevleri için queue .global(qos: .userInitiated) ve UI güncellemeleri için .main ile standart yaklaşımdır. Kuyruklar arasında sync işlemlerinden kaçının.
Android'de RecyclerView ve iOS'ta UICollectionView doğru yapılandırma gerektirir: onBindViewHolder'da minimum nesne oluşturma ile ViewHolder, değişiklik hesaplaması için DiffUtil, verileri önceden yüklemek için prefetching. iOS'ta manuel yönetim olmadan animasyonlu güncellemeler için diffable data source kullanın.
Her kaydırmada aynı görüntüyü yüklemek garantili gecikmedir. Coil (Android) ve Kingfisher (iOS) görüntüleri bellekte ve diskte önbelleğe alır, tekrarlanan isteklerde anında görüntüleme sağlar. Veriler için, Flow veya Combine tabanlı bir önbellek katmanı ile Room kullanın.
Android'de Coil ile görüntü önbelleğe alma yapılandırma örneği:
val imageLoader = ImageLoader(context) {
memoryCachePolicy(CachePolicy.ENABLED)
diskCachePolicy(CachePolicy.ENABLED)
crossfade(true)
size(512, 512)
}
// Loading with auto-caching enabled
imageView.load("https://example.com/image.jpg") {
placeholder(R.drawable.placeholder)
error(R.drawable.error)
}
Gecikmeyi önlemek, onu üretimde düzeltmekten daha ucuzdur. Önleyici tedbirler, araç ve mimari düzeyinde geliştirme sürecine yerleştirilir.
StrictMode, geliştirme sırasında ana iş parçacığındaki yanlışlıkla G/Ç işlemlerini ve ağ çağrılarını algılayan yerleşik bir Android aracıdır. Kritik ihlaller için penaltyDeath politikasıyla Application.onCreate'te etkinleştirin. Geliştiricinin sorunu commit'ten önce görmesini sağlamanın tek yolu budur.
iOS için eşdeğeri — Xcode'da Main Thread Checker, Runtime Sanitization'ın bir parçası — tüm UIKit ve AppKit çağrılarının ana iş parçacığında yürütülmesini otomatik olarak kontrol eder. Debug yapı şemasında etkinleştirin ve CI'da sıfır uyarı hedefleyin.
Başlangıç süresini, kaydırma FPS'sini ve bellek kullanımını ölçmek için CI boru hattınıza Macrobenchmark (Android) ve XCTMetrics (iOS) çalıştırmaları ekleyin. Eşikler belirleyin: yeni bir commit başlangıç süresini %5'ten fazla artırırsa — yapı başarısız olur.
Sıkça Sorulan Sorular
Gecikme, gecikmenin işlemeden değil giriş işleme süresinden kaynaklanması durumunda yüksek FPS'de bile oluşabilen öznel bir gecikme hissidir. Düşük FPS (30 fps'nin altı) gecikmenin bir nedenidir, ancak tek neden değildir.
Kareler arasındaki süreyi ölçmek için Android'de Frame Timing API (Choreographer) ve iOS'ta CADisplayLink kullanın. Google Play Vitals, gerçek koşullarda takılma oranını gösterir. Hassas ölçümler için kaydırma senaryolarıyla Macrobenchmark kullanın.
Eski cihazlar daha az CPU çekirdeğine, daha az RAM'e ve daha yavaş belleğe sahiptir. Bir amiral gemisinde 5 ms süren bir işlem, bütçe bir cihazda 50 ms sürebilir. Alt segment cihazlarda performansı test edin ve AOT derlemesi için Baseline Profiles ayarlayın.
Evet, bu en etkili yöntemlerden biridir. Yüksek çözünürlüklü görüntüler, kod çözme için çok fazla bellek ve CPU süresi tüketir. Görünüm boyutuna downscale, WebP (Android) ve HEIC (iOS) biçimleri ve Coil veya Kingfisher aracılığıyla önbelleğe alma kullanın.
SwiftUI, diffing yoluyla güncellemeleri otomatik olarak optimize eder, veri değiştiğinde gecikme riskini azaltır. Ancak karmaşık hiyerarşiler ve sık body yeniden oluşturmaları FPS düşüşüne neden olabilir. UIKit, performans üzerinde daha fazla kontrol sağlar ancak manuel optimizasyon gerektirir.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun