Jank — adalah istilah yang menunjukkan kegagapan yang terlihat atau “gagap” dalam animasi antarmuka, yang disebabkan oleh hilangnya bingkai individual. Dalam aplikasi seluler, Jank terjadi ketika waktu rendering bingkai melebihi anggaran yang dialokasikan oleh frekuensi penyegaran layar. Menurut Android Developers, 2025, Jank adalah penyebab utama perasaan subjektif “lembat” — aplikasi mungkin sempurna secara fungsional, tetapi pengguna menganggapnya lambat karena FPS yang tidak stabil.
Poin utama
Jank — adalah istilah dari grafis komputer yang menunjukkan cacat visual di mana animasi bergerak tersentak-sentak, bukan meluncur mulus. Dalam pengembangan seluler, Jank diukur sebagai jumlah bingkai yang terlewat (skipped frames) per satuan waktu. Jika sistem tidak sempat menyiapkan bingkai pada saat VSync, layar mengulang bingkai sebelumnya — terjadi jeda 16.6 ms pada 60 Hz. Satu bingkai yang terlewat mungkin tidak terlihat, tetapi rangkaian 3–5 bingkai yang terlewat secara berurutan menciptakan perasaan “lembat” selama 50–80 ms, yang jelas dirasakan pengguna.
Jank sangat kritis untuk animasi yang harus bekerja dengan kecepatan konstan: scrolling daftar, animasi pembukaan menu, efek paralaks, transisi antar layar. Menurut penelitian UX Google (2024), aplikasi dengan indikator Jank lebih dari 3% sesi scroll menerima 22% lebih banyak ulasan bintang satu dibandingkan aplikasi dengan indikator kurang dari 0.5%. Alat Android Vitals secara otomatis melacak Jank dan mengklasifikasikannya berdasarkan severity: moderate, severe, dan critical.
Penyebab Jank dibagi menjadi beberapa kategori. Pertama — Layout Jank: disebabkan oleh requestLayout() yang sering karena perubahan ukuran View, animasi LayoutTransition, atau pemuatan konten dinamis. Setiap panggilan requestLayout memicu Measure + Layout untuk seluruh sub-pohon View, yang dapat memakan waktu 5–30 ms. Kedua — Draw Jank: terkait dengan overdraw dan penggunaan drawable berat. Ketiga — Thread Jank: pemblokiran main thread karena operasi sinkron — memuat file, bekerja dengan database di thread utama, mendekode Bitmap.
Kategori keempat — GC Jank: garbage collection di ART/Dalvik atau Swift ARC. Ketika banyak objek menumpuk di heap, GC memicu jeda Stop-The-World selama 5–15 ms. Di Android, jeda GC paling sering terjadi pada alokasi sering di loop: pembuatan objek di onDraw(), alokasi di adapter, ekspresi lambda yang tidak digunakan. Kelima — IPC Jank: komunikasi antarproses (ContentProvider, Binder) di thread utama. Keenam — Rendering Jank: rendering GPU lambat karena shader yang tidak optimal atau tekstur berukuran besar.
| Tipe Jank | Penyebab | Durasi tipikal | Alat pencarian |
|---|---|---|---|
| Layout | requestLayout, relayout | 5–30 ms | Perfetto, Systrace |
| Draw | Overdraw, drawable berat | 3–20 ms | GPU Profiling |
| Thread | Pemblokiran main thread | 10–200 ms | Android Studio Profiler |
| GC | Garbage Collection | 5–15 ms | Memory Profiler |
| Rendering | Beban GPU | 10–50 ms | GPU Tracer, Xcode GPU |
Di Android, diagnosis Jank dimulai dengan trace sistem Perfetto. Perfetto merekam aktivitas semua thread, CPU, GPU, dan penjadwal. Indikator jelas Jank adalah baris Choreographer.doFrame dan Choreographer.doCallbacks: jika interval antara dua panggilan doFrame berurutan melebihi 16.6 ms, bingkai terlewat. Perfetto menunjukkan penyebab pasti — system call, lock, atau GC mana yang menyebabkan keterlambatan. Di Android Studio Profiler, fungsionalitas serupa tersedia melalui CPU Profiler.
Untuk deteksi otomatis Jank di produksi, digunakan FrameMetricsAggregator — API yang mengumpulkan statistik per bingkai dan menggabungkannya per sesi. Di Android 12+, muncul PerformanceHintManager — API untuk petunjuk ke sistem tentang kecepatan bingkai target. Jika aplikasi menunjukkan bahwa ia bekerja dalam skenario 120 FPS, sistem dapat meningkatkan frekuensi CPU/GPU untuk mencegah Jank. Untuk logging sederhana semua bingkai yang terlewat, cukup berlangganan ke Choreographer.FrameCallback.
Kode Kotlin berlangganan ke Choreographer.FrameCallback dan mencatat setiap bingkai yang terlewat dengan menyebutkan durasi keterlambatan. Callback dipanggil pada setiap VSync.
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",
"$skippedFrames bingkai terlewat")
}
}
previousFrameTime = currentTime
Choreographer.getInstance()
.postFrameCallback(this)
}
fun start() {
Choreographer.getInstance()
.postFrameCallback(callback)
}
}
Di iOS, diagnosis Jank dilakukan melalui Instruments dengan templat Core Animation. Instruments menampilkan FPS real-time, jumlah render offscreen, dan hit-test. Indikator utama Jank di iOS: kolom merah di skala waktu Core Animation (melebihi anggaran bingkai), indikator Renderer tinggi (berarti offscreen rendering), dan FPS rendah. Untuk pemantauan produksi, MetricKit mengumpulkan laporan dengan metrik MXAnimatoryMetric, yang mencakup FPS rata-rata, P50 dan P95 waktu bingkai.
Diagnosis asli Jank di iOS mencakup CADisplayLink dengan pemeriksaan timestamp dan targetTimestamp. Jika timestamp saat ini tertinggal signifikan dari targetTimestamp, berarti satu atau lebih bingkai terlewat. Apple juga merekomendasikan penggunaan os_signpost untuk pembuatan profil kustom: tempatkan signpost-interval di awal dan akhir rendering bingkai dan periksa di Instruments interval mana yang melebihi 16.6 ms. Di SwiftUI, untuk diagnosis Jank digunakan UIView.invalidateIntrinsicContentSize — panggilan sering metode ini menunjukkan Layout yang tidak stabil.
Kode Swift mendeteksi bingkai yang terlewat melalui CADisplayLink. Jika selisih antara timestamp dan targetTimestamp melebihi 16.6 ms — Jank dicatat.
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
}
}
}
Untuk pembuatan profil Jank, digunakan baik alat bawaan OS maupun SDK pihak ketiga. Di Android, alat kuncinya adalah Perfetto (menggantikan Systrace). Perfetto memungkinkan merekam trace hingga 30 detik dan menganalisisnya melalui antarmuka web ui.perfetto.dev. Ini menunjukkan garis waktu yang tepat dengan aktivitas Choreographer, thread rendering (RenderThread), dan GPU. Untuk analisis mendetail masalah GPU, digunakan AGI (Android GPU Inspector), yang menunjukkan tidak hanya waktu bingkai tetapi juga beban blok GPU spesifik — shader, rasterizer, blok tekstur.
Di iOS, padanannya adalah Instruments dengan templat Core Animation, Metal System Trace, dan GPU Driver. Core Animation menampilkan FPS dan waktu bingkai, Metal System Trace — kerja GPU dengan detail hingga setiap draw call. Untuk pembuatan profil di perangkat nyata di bawah beban, digunakan Firebase Performance (mengumpulkan metrik Screen Rendering) dan Sentry(menangkap stack trace saat Jank). API baru Android 15 Performance Hint memungkinkan pengembang menunjukkan ke sistem bingkai mana yang penting dan menerima peringatan dari sistem saat mendekati Jank.
Kode Kotlin menggunakan FrameMetricsAggregator untuk mengumpulkan statistik bingkai per sesi. Setelah menghentikan aggregator, jumlah bingkai yang terlewat ditampilkan.
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",
"Rasio Jank: ${jankFrames * 100 / totalFrames}%")
}
}
Mengatasi Jank memerlukan kombinasi metode tergantung tipenya. Untuk Layout Jank: mengganti hierarki dalam dengan ConstraintLayout/Compose/SwiftUI, menggunakan merge-tag, menghindari requestLayout dalam animasi. Untuk Draw Jank: menggunakan Debug GPU Overdraw untuk menemukan overdraw 4x+, mengganti drawable berat dengan vektor (VectorDrawable/PDF), menggunakan hardware layers dengan hati-hati — mempercepat rendering tetapi menggunakan lebih banyak memori GPU. Untuk Thread Jank: memindahkan semua operasi I/O, kerja database, dan dekode Bitmap ke thread latar belakang, menggunakan Kotlin Coroutines dengan Dispatcher yang tepat atau RxJava dengan Schedulers.io().
Untuk GC Jank: meminimalkan alokasi di onDraw() dan getView(), menggunakan object pool (ObjectPool), mengganti for-each dengan for berindeks, menggunakan immutable data class di Kotlin dengan copy() secara hati-hati — copy membuat objek baru. Untuk IPC Jank: inisialisasi malas ContentProvider melalui App Startup, memindahkan panggilan Binder ke thread latar belakang. Untuk Rendering Jank: mengurangi ukuran tekstur hingga resolusi maksimum layar, menggunakan kompresi ASTC atau ETC2, menghindari shader compilation yang tidak perlu (mengompilasi shader terlebih dahulu). Solusi komprehensif — menjalankan profil Perfetto/Instruments secara teratur di CI dan melacak regresi Jank.
Kode Kotlin mendemonstrasikan pemuatan data asinkron ke layar setelah reportFullyDrawn, sehingga pekerjaan berat tidak memblokir bingkai pertama. Callback dipanggil setelah pengguna melihat antarmuka.
class JankSafeLoader {
suspend fun loadAfterFirstFrame(
activity: Activity
) {
// menjamin bahwa bingkai pertama sudah dirender
if (Build.VERSION.SDK_INT >= 29) {
activity.reportFullyDrawn()
}
// beban berat — setelah bingkai pertama
withContext(Dispatchers.IO) {
val data = fetchHeavyData()
withContext(Dispatchers.Main) {
updateUI(data)
}
}
}
}
Pertanyaan yang sering diajukan
Jank — adalah bingkai rendering yang terlewat yang muncul sebagai kegagapan atau sentakan animasi yang terlihat. Terjadi ketika waktu persiapan bingkai melebihi anggaran waktu (16.6 ms untuk 60 FPS).
Layout Jank (sering requestLayout), Draw Jank (overdraw), Thread Jank (pemblokiran main thread), GC Jank (garbage collection), IPC Jank (panggilan Binder), dan Rendering Jank (shader berat).
Gunakan Perfetto untuk trace sistem, GPU Profiling untuk analisis fase bingkai, dan FrameMetricsAggregator untuk pemantauan produksi. Di Android Studio — CPU Profiler dengan Deep Java Trace.
Melalui Instruments dengan templat Core Animation atau Metal System Trace. Untuk produksi — MetricKit dengan MXAnimatoryMetric. Secara terprogram — CADisplayLink dengan memeriksa selisih timestamp dan targetTimestamp.
Menurut Google, indikator Jank lebih dari 3% sesi scroll (3 dari 100 scroll mengandung kegagapan) menyebabkan peningkatan ulasan negatif sebesar 22%. Indikator target — kurang dari 0.5% sesi scroll.
Ringkasan
Kami akan mengembangkan aplikasi seluler turnkey
IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.
Baca juga