Jank, bireysel karelerin atlanması nedeniyle arayüz animasyonunda gözle görülür takılmaları veya “kekemeleri” ifade eden bir terimdir. Mobil uygulamalarda Jank, kare oluşturma süresinin ekran yenileme hızı tarafından ayrılan bütçeyi aşması durumunda ortaya çıkar. Android Developers, 2025'e göre, Jank “yavaşlık” öznel hissinin ana nedenidir — bir uygulama işlevsel olarak mükemmel olabilir, ancak kullanıcı dengesiz FPS nedeniyle onu yavaş olarak algılar.
Önemli Noktalar
Jank, bilgisayar grafikleri alanında animasyonun pürüzsüz kayma yerine sarsıntılı hareket ettiği görsel bir kusuru ifade eden bir terimdir. Mobil geliştirmede Jank, birim zaman başına atlanan kare sayısı (skipped frames) olarak ölçülür. Sistem VSync zamanına kadar bir kare hazırlayamazsa, ekran önceki kareyi tekrarlar — 60 Hz'de 16,6 ms'lik bir duraklama oluşur. Tek bir atlanan kare fark edilmeyebilir, ancak 3–5 ardışık atlanan kare dizisi, kullanıcının açıkça algıladığı 50–80 ms süren bir “takılma” hissi yaratır.
Jank, sabit hızda çalışması gereken animasyonlar için özellikle kritiktir: beslemelerde kaydırma, menü açma animasyonu, paralaks efektleri, ekranlar arası geçişler. Google UX araştırmasına (2024) göre, kaydırma oturumlarının %3'ünden fazlasında Jank oranı olan bir uygulama, oranı %0,5'in altında olan bir uygulamadan %22 daha fazla bir yıldızlı inceleme alır. Android Vitals aracı Jank'ı otomatik olarak izler ve ciddiyetine göre sınıflandırır: orta, şiddetli ve kritik.
Jank'ın nedenleri birkaç kategoriye ayrılır. Birincisi Layout Jank: View boyutlarındaki değişiklikler, LayoutTransition animasyonları veya dinamik içerik yüklemesi nedeniyle sık requestLayout() çağrılarından kaynaklanır. Her requestLayout çağrısı, tüm View alt ağacı için Measure + Layout'u tetikler ve bu 5–30 ms sürebilir. İkincisi Draw Jank: overdraw ve ağır drawable kullanımıyla ilgilidir. Üçüncüsü Thread Jank: senkron işlemler (dosya yükleme, ana iş parçacığında veritabanı işlemleri, Bitmap kod çözme) nedeniyle ana iş parçacığının bloke edilmesidir.
Dördüncü kategori GC Jank: ART/Dalvik veya Swift ARC'da çöp toplama (Garbage Collection). Yığında çok sayıda nesne biriktiğinde, GC 5–15 ms süren bir Stop-The-World duraklaması başlatır. Android'de, GC duraklamaları en sık döngülerde sık tahsisler sırasında meydana gelir: onDraw()'da nesne oluşturma, bağdaştırıcılarda tahsis, kullanılmayan lambda ifadeleri. Beşincisi IPC Jank: ana iş parçacığında süreçler arası iletişim (ContentProvider, Binder). Altıncısı Rendering Jank: optimal olmayan gölgelendiriciler veya büyük boyutlu dokular nedeniyle yavaş GPU oluşturma.
| Jank Türü | Neden | Tipik Süre | Tespit Aracı |
|---|---|---|---|
| Layout | requestLayout, relayout | 5–30 ms | Perfetto, Systrace |
| Draw | Overdraw, ağır drawable | 3–20 ms | GPU Profiling |
| Thread | Ana iş parçacığı blokajı | 10–200 ms | Android Studio Profiler |
| GC | Garbage Collection | 5–15 ms | Memory Profiler |
| Rendering | GPU yükü | 10–50 ms | GPU Tracer, Xcode GPU |
Android'de Jank teşhisi, Perfetto sistem izi ile başlar. Perfetto, tüm iş parçacıklarının, CPU'nun, GPU'nun ve zamanlayıcının etkinliğini kaydeder. Jank'ın net bir göstergesi, Choreographer.doFrame ve Choreographer.doCallbacks satırlarıdır: ardışık iki doFrame çağrısı arasındaki aralık 16,6 ms'yi aşarsa, bir kare atlanmıştır. Perfetto kesin nedeni gösterir — hangi sistem çağrısı, kilit veya GC gecikmeye neden oldu. Android Studio Profiler'da, CPU Profiler aracılığıyla benzer işlevsellik mevcuttur.
Üretimde otomatik Jank tespiti için FrameMetricsAggregator kullanılır — her kare için istatistik toplayan ve bunları oturum bazında birleştiren bir API. Android 12+'da PerformanceHintManager ortaya çıktı — sisteme hedef kare hızı hakkında ipucu vermek için bir API. Uygulama 120 FPS senaryosunda çalıştığını belirtirse, sistem Jank'ı önlemek için CPU/GPU frekansını artırabilir. Atlanan tüm karelerin basit günlüğü için Choreographer.FrameCallback'e abone olmak yeterlidir.
Kotlin kodu Choreographer.FrameCallback'e abone olur ve gecikme süresiyle birlikte atlanan her kareyi günlüğe kaydeder. Geri çağrı her VSync'te çağrılır.
class JankDetector {
private val frameBudget = 16_666_666L
private var previousFrameTime = 0L
private val callback =
Choreographer.FrameCallback { currentTime ->
if (previousFrameTime != 0L) {
val frameDuration =
currentTime - previousFrameTime
val skippedFrames =
(frameDuration / frameBudget) - 1
if (skippedFrames > 0) {
Log.w("Jank",
"Skipped $skippedFrames frames")
}
}
previousFrameTime = currentTime
Choreographer.getInstance()
.postFrameCallback(this)
}
fun start() {
Choreographer.getInstance()
.postFrameCallback(callback)
}
}
iOS'ta Jank teşhisi, Core Animation şablonuyla Instruments aracılığıyla gerçekleştirilir. Instruments, gerçek zamanlı FPS, ekran dışı oluşturma sayısını ve isabet testlerini gösterir. iOS'ta Jank'ın ana göstergeleri: Core Animation zaman çizelgesinde kırmızı çubuklar (kare bütçesi aşıldı), yüksek Renderer değeri (ekran dışı oluşturmayı gösterir) ve düşük FPS. Üretim izlemesi için MetricKit, ortalama FPS, P50 ve P95 kare süresini içeren MXAnimatoryMetric metriğiyle raporlar toplar.
iOS'ta yerel Jank teşhisi, zaman damgası ve targetTimestamp kontrolü ile CADisplayLink'i içerir. Geçerli zaman damgası targetTimestamp'ten önemli ölçüde geriyse, bir veya daha fazla kare atlanmıştır. Apple ayrıca özel profilleme için os_signpost kullanılmasını önerir: kare oluşturmanın başına ve sonuna bir signpost-interval yerleştirin ve Instruments'ta hangi aralıkların 16,6 ms'yi aştığını kontrol edin. SwiftUI'de, Jank teşhisi için UIView.invalidateIntrinsicContentSize kullanılır — bu yöntemin sık çağrılması kararsız Layout'u gösterir.
Swift kodu, CADisplayLink aracılığıyla atlanan kareleri tespit eder. Zaman damgası ile targetTimestamp arasındaki fark 16,6 ms'yi aşarsa, Jank kaydedilir.
class JankMonitor {
private var displayLink: CADisplayLink?
private var totalJank = 0
func start() {
displayLink = CADisplayLink(
target: self,
selector: #selector(detectJank)
)
displayLink?.add(to: .current,
forMode: .common)
}
@objc
private func detectJank() {
guard let link = displayLink else { return }
let delay = link.targetTimestamp
- link.timestamp
if delay > 0.0167 {
totalJank += 1
}
}
}
Jank profillemesi için hem işletim sistemi yerleşik araçları hem de üçüncü taraf SDK'lar kullanılır. Android'de temel araç Perfetto'dur (Systrace'in yerini almıştır). Perfetto, 30 saniyeye kadar iz kaydedebilir ve bunları ui.perfetto.dev web arayüzü üzerinden analiz edebilir. Choreographer etkinliği, oluşturma iş parçacıkları (RenderThread) ve GPU ile kesin bir zaman çizelgesi gösterir. GPU sorunlarının ayrıntılı analizi için AGI (Android GPU Inspector) kullanılır; bu araç yalnızca kare süresini değil, aynı zamanda belirli GPU bloklarının (gölgelendiriciler, rasterleştirici, doku birimi) yükünü de gösterir.
iOS'ta eşdeğeri, Core Animation, Metal System Trace ve GPU Driver şablonlarıyla Instruments'tır. Core Animation FPS ve kare süresini gösterir, Metal System Trace her draw call'a kadar GPU çalışmasını gösterir. Yük altındaki gerçek cihazlarda profilleme için Firebase Performance (Screen Rendering metriğini toplar) ve Sentry (Jank'ta yığın izi yakalar) kullanılır. Yeni Android 15 Performance Hint API'si, geliştiricinin sisteme hangi karelerin önemli olduğunu bildirmesine ve Jank yaklaştığında sistemden uyarı almasına olanak tanır.
Kotlin kodu, bir oturum boyunca kare istatistikleri toplamak için FrameMetricsAggregator'ı kullanır. Toplayıcı durdurulduktan sonra, atlanan kare sayısı görüntülenir.
class JankAggregator(private val activity: Activity) {
private val aggregator = FrameMetricsAggregator()
fun startCollection() {
aggregator.add(activity.window)
}
fun stopAndReport() {
aggregator.remove()
val result = aggregator.getMetrics()
val totalFrames = result
?.get(FrameMetrics.TOTAL_DURATION)
?.size ?: 0
val jankFrames = result
?.get(FrameMetrics.TOTAL_DURATION)
?.count { it > 16_666_666L} ?: 0
Log.d("JankReport",
"Jank ratio: \${jankFrames * 100 / totalFrames}%")
}
}
Jank'ı ortadan kaldırmak, türüne bağlı olarak tekniklerin bir kombinasyonunu gerektirir. Layout Jank için: derin hiyerarşileri ConstraintLayout/Compose/SwiftUI ile değiştirin, merge etiketleri kullanın, animasyonlarda requestLayout'tan kaçının. Draw Jank için: 4x+ overdraw bulmak için Debug GPU Overdraw kullanın, ağır drawable'ları vektör grafiklerle (VectorDrawable/PDF) değiştirin, donanım katmanlarını dikkatli kullanın — oluşturmayı hızlandırır ancak daha fazla GPU belleği tüketir. Thread Jank için: tüm G/Ç işlemlerini, veritabanı işlerini ve Bitmap kod çözmeyi arka plan iş parçacıklarına taşıyın, doğru Dispatcher ile Kotlin Coroutines veya Schedulers.io() ile RxJava kullanın.
GC Jank için: onDraw() ve getView()'de tahsisleri en aza indirin, nesne havuzları (ObjectPool) kullanın, for-each'i indeksli for ile değiştirin, Kotlin'de copy() ile değişmez data class'ı dikkatli kullanın — copy yeni bir nesne oluşturur. IPC Jank için: App Startup aracılığıyla ContentProvider'ı tembel başlatın, Binder çağrılarını arka plan iş parçacığına taşıyın. Rendering Jank için: doku boyutlarını maksimum ekran çözünürlüğüne düşürün, ASTC veya ETC2 sıkıştırması kullanın, aşırı gölgelendirici derlemesinden kaçının (gölgelendiricileri önceden derleyin). Kapsamlı bir çözüm, CI'da düzenli Perfetto/Instruments profillemesi ve Jank gerilemelerinin izlenmesidir.
Kotlin kodu, reportFullyDrawn sonrasında ekrana verilerin eşzamansız olarak yüklenmesini gösterir, böylece ağır iş ilk kareyi engellemez. Geri çağrı, kullanıcı arayüzü gördükten sonra çağrılır.
class JankSafeLoader {
suspend fun loadAfterFirstFrame(
activity: Activity
) {
// ilk karenin zaten oluşturulduğunu garanti et
if (Build.VERSION.SDK_INT >= 29) {
activity.reportFullyDrawn()
}
// ağır yükleme — ilk kareden sonra
withContext(Dispatchers.IO) {
val data = fetchHeavyData()
withContext(Dispatchers.Main) {
updateUI(data)
}
}
}
}
Sıkça Sorulan Sorular
Jank, animasyonda gözle görülür takılmalar veya sarsıntılar olarak ortaya çıkan atlanmış oluşturma kareleridir. Kare hazırlama süresinin zaman bütçesini (60 FPS için 16,6 ms) aşması durumunda oluşur.
Layout Jank (sık requestLayout), Draw Jank (overdraw), Thread Jank (ana iş parçacığı blokajı), GC Jank (çöp toplama), IPC Jank (Binder çağrıları) ve Rendering Jank (ağır gölgelendiriciler).
Sistem izlemesi için Perfetto, kare aşaması analizi için GPU Profiling ve üretim izlemesi için FrameMetricsAggregator kullanın. Android Studio'da — Deep Java Trace ile CPU Profiler.
Instruments ile Core Animation veya Metal System Trace şablonu kullanarak. Üretim için — MXAnimatoryMetric ile MetricKit. Programlı olarak — zaman damgası ve targetTimestamp arasındaki farkı kontrol eden CADisplayLink.
Google'a göre, kaydırma oturumlarının %3'ünden fazlasında Jank oranı (100 kaydırmadan 3'ü takılma içerir) olumsuz yorumlarda %22 artışa yol açar. Hedef oran, kaydırma oturumlarının %0,5'inden azıdır.
Ö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