Jank — bu interfeys animatsiyasida sezilarli tiqilishlar yoki “duduqlanishlar” degan ma'noni anglatuvchi atama bo'lib, alohida kadrlarning o'tkazib yuborilishi natijasida yuzaga keladi. Mobil ilovalarda Jank kadr renderlash vaqti displey yangilanish chastotasi tomonidan ajratilgan byudjetdan oshib ketganda yuzaga keladi. Android Developers, 2025 ma'lumotlariga ko'ra, Jank subyektiv “sekinlashish” hissining asosiy sababidir — ilova funksional jihatdan mukammal bo'lishi mumkin, ammo foydalanuvchi uni beqaror FPS tufayli sekin deb qabul qiladi.
Asosiy ma'lumotlar
Jank — kompyuter grafikasi sohasida animatsiya silliq sirpanish o'rniga sakrashlar bilan harakatlanadigan vizual nuqsonni anglatuvchi atamadir. Mobil ishlanmada Jank vaqt birligidagi o'tkazib yuborilgan kadrlar soni (skipped frames) bilan o'lchanadi. Agar tizim VSync vaqtigacha kadrni tayyorlashga ulgurmasa, displey oldingi kadrni takrorlaydi — 60 Hz da 16.6 ms davom etadigan pauza yuzaga keladi. Bitta o'tkazib yuborilgan kadr sezilmasligi mumkin, ammo ketma-ket 3–5 ta o'tkazib yuborilgan kadrlar seriyasi foydalanuvchi aniq sezadigan 50–80 ms davom etadigan “sekinlashish” hissini yaratadi.
Jank ayniqsa doimiy tezlikda ishlashi kerak bo'lgan animatsiyalar uchun muhim: ro'yxatni aylantirish, menyu ochish animatsiyasi, parallaks effektlari, ekranlar orasidagi o'tishlar. Google UX tadqiqotiga (2024) ko'ra, Jank ko'rsatkichi aylantirish sessiyalarining 3% dan yuqori bo'lgan ilova, ko'rsatkichi 0.5% dan past bo'lgan ilovaga nisbatan 22% ko'proq bir yulduzli sharhlarni oladi. Android Vitals vositasi avtomatik ravishda Jankni kuzatadi va severity bo'yicha tasniflaydi: moderate, severe va critical.
Jank sabablari bir necha toifalarga bo'linadi. Birinchi — Layout Jank: View o'lchamlarining o'zgarishi, LayoutTransition animatsiyalari yoki dinamik kontent yuklanishi sababli tez-tez requestLayout() chaqiruvlari natijasida yuzaga keladi. Har bir requestLayout chaqiruvi butun View pastki daraxti uchun Measure + Layout ni ishga tushiradi, bu 5–30 ms vaqt olishi mumkin. Ikkinchi — Draw Jank: haddan tashqari chizish (overdraw) va og'ir drawable-lardan foydalanish bilan bog'liq. Uchinchi — Thread Jank: sinxron operatsiyalar — fayl yuklash, asosiy oqimda ma'lumotlar bazasi bilan ishlash, Bitmap dekodlash tufayli main thread bloklanishi.
To'rtinchi toifa — GC Jank: ART/Dalvik yoki Swift ARC da garbage collection. Yig'ishda ko'plab ob'ektlar to'planganda, GC 5–15 ms davom etadigan Stop-The-World pauzasini ishga tushiradi. Android-da GC pauzalari ko'pincha sikllarda tez-tez alokatsiyalar paytida yuzaga keladi: onDraw() da ob'ekt yaratish, adapterlardagi alokatsiyalar, foydalanilmaydigan lambda ifodalari. Beshinchi — IPC Jank: asosiy oqimda jarayonlararo aloqa (ContentProvider, Binder). Oltinchi — Rendering Jank: optimal bo'lmagan shaderlar yoki katta o'lchamdagi teksturalar tufayli sekin GPU renderi.
| Jank turi | Sabab | Odatdagi davomiylikQidiruv vositasi | |
|---|---|---|---|
| Layout | requestLayout, relayout | 5–30 ms | Perfetto, Systrace |
| Draw | Overdraw, og'ir drawable | 3–20 ms | GPU Profiling |
| Thread | Main thread bloklanishi | 10–200 ms | Android Studio Profiler |
| GC | Garbage Collection | 5–15 ms | Memory Profiler |
| Rendering | GPU yuklanishi | 10–50 ms | GPU Tracer, Xcode GPU |
Android-da Jank diagnostikasi tizim treysi Perfetto bilan boshlanadi. Perfetto barcha oqimlar, CPU, GPU va rejalashtiruvchining faoliyatini qayd etadi. Jankning aniq ko'rsatkichi Choreographer.doFrame va Choreographer.doCallbacks satrlaridir: ikkita ketma-ket doFrame chaqiruvi orasidagi interval 16.6 ms dan oshsa, kadr o'tkazib yuborilgan. Perfetto aniq sababni ko'rsatadi — qaysi system call, lock yoki GC kechikishga sabab bo'lgan. Android Studio Profiler da shunga o'xshash funksionallik CPU Profiler orqali mavjud.
Ishlab chiqarishda Jankni avtomatik aniqlash uchun FrameMetricsAggregator ishlatiladi — har bir kadr bo'yicha statistika to'playdigan va sessiya bo'yicha jamlaydigan API. Android 12+ da PerformanceHintManager paydo bo'ldi — tizimga maqsadli kadr chastotasi haqida ko'rsatma berish uchun API. Ilova 120 FPS stsenariysida ishlayotganini ko'rsatsa, tizim Jankning oldini olish uchun CPU/GPU chastotasini oshirishi mumkin. Barcha o'tkazib yuborilgan kadrlarni oddiy loglash uchun Choreographer.FrameCallback ga obuna bo'lish kifoya.
Kotlin kodi Choreographer.FrameCallback ga obuna bo'ladi va kechikish muddatini ko'rsatgan holda har bir o'tkazib yuborilgan kadrni loglaydi. Callback har bir VSync da chaqiriladi.
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 kadr o'tkazib yuborildi")
}
}
previousFrameTime = currentTime
Choreographer.getInstance()
.postFrameCallback(this)
}
fun start() {
Choreographer.getInstance()
.postFrameCallback(callback)
}
}
iOS-da Jank diagnostikasi Core Animation andozasi bilan Instruments orqali amalga oshiriladi. Instruments real vaqtda FPS, offscreen-renderlar soni va hit-testlarni ko'rsatadi. iOS-da Jankning asosiy ko'rsatkichlari: Core Animation vaqt shkalasida qizil ustunlar (kadr byudjetining oshib ketishi), yuqori Renderer ko'rsatkichi (offscreen rendering ma'nosida) va past FPS. Ishlab chiqarish monitoringi uchun MetricKit o'rtacha FPS, P50 va P95 kadr vaqtini o'z ichiga olgan MXAnimatoryMetric metrikasi bilan hisobotlarni to'playdi.
iOS-da Jankning mahalliy diagnostikasi timestamp va targetTimestamp tekshiruvi bilan CADisplayLink ni o'z ichiga oladi. Agar joriy timestamp targetTimestamp dan sezilarli darajada orqada qolsa, bir yoki bir nechta kadr o'tkazib yuborilgan. Apple shuningdek maxsus profillash uchun os_signpost dan foydalanishni tavsiya qiladi: kadr renderining boshida va oxirida signpost-interval joylashtirish va Instruments da qaysi intervallar 16.6 ms dan oshganini tekshirish. SwiftUI da Jank diagnostikasi uchun UIView.invalidateIntrinsicContentSize ishlatiladi — bu usulning tez-tez chaqirilishi beqaror Layoutni ko'rsatadi.
Swift kodi CADisplayLink orqali o'tkazib yuborilgan kadrlarni aniqlaydi. Timestamp va targetTimestamp orasidagi farq 16.6 ms dan oshsa — Jank qayd etiladi.
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 profilingi uchun ham operatsion tizimning o'rnatilgan vositalari, ham uchinchi tomon SDK-lari ishlatiladi. Android-da asosiy vosita Perfetto dir (Systrace o'rnini egalladi). Perfetto 30 soniyagacha treyslarni yozib olish va ularni ui.perfetto.dev veb interfeysi orqali tahlil qilish imkonini beradi. U Choreographer, render oqimlari (RenderThread) va GPU ishining aniq vaqt shkalasini ko'rsatadi. GPU bilan bog'liq muammolarni batafsil tahlil qilish uchun AGI (Android GPU Inspector) ishlatiladi, u nafaqat kadr vaqtini, balki GPU ning aniq bloklari — shaderlar, rastrlashtiruvchi, tekstura blokining yuklanishini ham ko'rsatadi.
iOS-da analog — Instruments Core Animation, Metal System Trace va GPU Driver andozalari bilan. Core Animation FPS va kadr vaqtini, Metal System Trace — har bir draw call gacha aniqlikda GPU ishini ko'rsatadi. Haqiqiy qurilmalarda yuk ostida profillash uchun Firebase Performance (Screen Rendering metrikasini to'playdi) va Sentry (Jank vaqtida stack trace ni ushlaydi) ishlatiladi. Yangi Android 15 Performance Hint API ishlab chiquvchiga tizimga qaysi kadrlar muhimligini ko'rsatishga va Jankka yaqinlashganda tizimdan ogohlantirishlar olishga imkon beradi.
Kotlin kodi sessiya bo'yicha kadr statistikasini to'plash uchun FrameMetricsAggregator dan foydalanadi. Agregator to'xtatilgandan so'ng o'tkazib yuborilgan kadrlar soni ko'rsatiladi.
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 nisbati: ${jankFrames * 100 / totalFrames}%")
}
}
Jank ni bartaraf etish uning turiga qarab usullar kombinatsiyasini talab qiladi. Layout Jank uchun: chuqur iyerarxiyalarni ConstraintLayout/Compose/SwiftUI bilan almashtirish, merge-teglardan foydalanish, animatsiyalarda requestLayout dan qochish. Draw Jank uchun: 4x+ overdraw ni topish uchun Debug GPU Overdraw dan foydalanish, og'ir drawable-larni vektor (VectorDrawable/PDF) bilan almashtirish, hardware layers dan ehtiyotkorona foydalanish — ular renderni tezlashtiradi, lekin ko'proq GPU xotirasini sarflaydi. Thread Jank uchun: barcha I/O operatsiyalari, ma'lumotlar bazasi bilan ishlash va Bitmap dekodlashni fon oqimlariga o'tkazish, to'g'ri Dispatcher bilan Kotlin Coroutines yoki Schedulers.io() bilan RxJava ishlatish.
GC Jank uchun: onDraw() va getView() da alokatsiyalarni minimallashtirish, ob'ekt hovuzlaridan (ObjectPool) foydalanish, for-each ni indeksli for bilan almashtirish, Kotlin da immutable data class va copy() dan ehtiyotkorona foydalanish — copy yangi ob'ekt yaratadi. IPC Jank uchun: ContentProvider ni App Startup orqali dangasa ishga tushirish, Binder chaqiruvlarini fon oqimiga o'tkazish. Rendering Jank uchun: tekstura o'lchamini ekranning maksimal rezolyutsiyasigacha kamaytirish, ASTC yoki ETC2 siqishdan foydalanish, keraksiz shader compilation dan qochish (shaderlarni oldindan kompilyatsiya qilish). Kompleks yechim — CI da muntazam Perfetto/Instruments profilingini ishga tushirish va Jank regressiyalarini kuzatish.
Kotlin kodi reportFullyDrawn dan keyin ekranga asinxron ma'lumot yuklashni namoyish etadi, shunda og'ir ish birinchi kadrni bloklamaydi. Callback foydalanuvchi interfeysni ko'rganidan keyin chaqiriladi.
class JankSafeLoader {
suspend fun loadAfterFirstFrame(
activity: Activity
) {
// birinchi kadr allaqachon chizilganligiga kafolat beramiz
if (Build.VERSION.SDK_INT >= 29) {
activity.reportFullyDrawn()
}
// og'ir yuklash — birinchi kadrdan keyin
withContext(Dispatchers.IO) {
val data = fetchHeavyData()
withContext(Dispatchers.Main) {
updateUI(data)
}
}
}
}
Ko'p beriladigan savollar
Jank — render kadrlarining sezilarli tiqilishlar yoki animatsiya silkishlari ko'rinishidagi o'tkazib yuborilgan kadrlardir. Kadr tayyorlash vaqti vaqt byudjetidan (60 FPS uchun 16.6 ms) oshib ketganda yuzaga keladi.
Layout Jank (tez-tez requestLayout), Draw Jank (overdraw), Thread Jank (main thread bloklanishi), GC Jank (garbage collection), IPC Jank (Binder chaqiruvlari) va Rendering Jank (og'ir shaderlar).
Tizim treysi uchun Perfetto, kadr fazalarini tahlil qilish uchun GPU Profiling va ishlab chiqarish monitoringi uchun FrameMetricsAggregator dan foydalaning. Android Studio da — CPU Profiler Deep Java Trace bilan.
Core Animation yoki Metal System Trace andozasi bilan Instruments orqali. Ishlab chiqarish uchun — MXAnimatoryMetric bilan MetricKit. Dasturiy ravishda — timestamp va targetTimestamp farqini tekshirish bilan CADisplayLink.
Google ma'lumotlariga ko'ra, aylantirish sessiyalarining 3% dan yuqori Jank ko'rsatkichi (100 aylantirishdan 3 tasi tiqilishni o'z ichiga oladi) salbiy sharhlarning 22% ga oshishiga olib keladi. Maqsadli ko'rsatkich — aylantirish sessiyalarining 0.5% dan kam.
Xulosa
Biz kalit topshirig'i bilan mobil ilovani ishlab chiqamiz
IT Sectr 2017-yildan beri startaplar va korxonalar uchun iOS va Android ilovalarini yaratadi. Biz sizga maslahat beramiz va eng yaxshi yechimni taklif qilamiz.