Jank mobilalkalmazásokhoz — mi ez, okai és megszüntetése

Szerző: IT Sectr Megjelenés: 2026-04-01 Olvasási idő: 10 perc

Jank — olyan kifejezés, amely a felületi animáció észrevehető akadozását vagy „dadogását” jelöli, amelyet egyes képkockák kihagyása okoz. Mobilalkalmazásokban a Jank akkor lép fel, amikor egy képkocka renderelési ideje meghaladja a kijelző frissítési gyakorisága által elkülönített költségvetést. A Android Developers, 2025 szerint a Jank a szubjektív „lassulás” érzésének fő oka — az alkalmazás funkcionálisan tökéletes lehet, de a felhasználó lassúnak érzékeli az instabil FPS miatt.

Főbb pontok

  • Jank — kihagyott képkockák, amelyek az animáció akadozásaként észlelhetők.
  • Fő ok — a képkockánkénti időkeret túllépése (16.6 ms 60 FPS esetén).
  • A Jank nehéz Layout, hosszú GC, main thread blokkolás vagy overdraw miatt alakul ki.
  • Diagnosztikához a FrameTimeline (Android) és Instruments (iOS) használatos.
  • A Jank megszüntetése 15–25%-kal növeli az NPS-t és a felhasználói megtartást.

Mi az a Jank

Jank — a számítógépes grafika területéről származó kifejezés, amely olyan vizuális hibát jelöl, ahol az animáció a sima csúszás helyett rángatózva mozog. Mobil fejlesztésben a Jank az időegységre jutó kihagyott képkockák számával (skipped frames) mérhető. Ha a rendszer nem tud egy képkockát előkészíteni a VSync pillanatára, a kijelző megismétli az előző képkockát — 16.6 ms-os szünet keletkezik 60 Hz-en. Egy kihagyott képkocka észrevétlen lehet, de 3–5 egymást követő kihagyott képkocka sorozata 50–80 ms-os „lassulás” érzést kelt, amit a felhasználó egyértelműen érzékel.

A Jank különösen kritikus azoknál az animációknál, amelyeknek állandó sebességgel kell működniük: lista görgetése, menü nyitás animációja, parallaxis effektek, képernyők közötti átmenetek. A Google UX-kutatása (2024) szerint az a Jank-mutatóval rendelkező alkalmazás, amely a görgetési munkamenetek több mint 3%-ánál produkál Jank-ot, 22%-kal több egycsillagos értékelést kap, mint az a 0.5% alatti mutatójú alkalmazás. Az Android Vitals eszköz automatikusan nyomon követi a Jank-ot és severity szerint osztályozza: moderate, severe és critical.

A Jank fő okai

A Jank okai több kategóriába sorolhatók. Az első — Layout Jank: gyakori requestLayout() hívások okozzák a View méreteinek változása, LayoutTransition animációk vagy dinamikus tartalom betöltése miatt. Minden requestLayout hívás elindítja a Measure + Layout-ot a teljes View részfára vonatkozóan, ami 5–30 ms-ig tarthat. A második — Draw Jank: overdraw-hoz és nehéz drawable-ok használatához kapcsolódik. A harmadik — Thread Jank: a main thread blokkolása szinkron műveletek miatt — fájlok betöltése, adatbázis-munka a fő szálon, Bitmap dekódolás.

A negyedik kategória — GC Jank: garbage collection az ART/Dalvik vagy Swift ARC rendszerben. Amikor sok objektum halmozódik fel a heap-en, a GC 5–15 ms-os Stop-The-World szünetet indít. Androidon a GC-szünetek leggyakrabban gyakori allokációknál fordulnak elő ciklusokban: objektumok létrehozása onDraw()-ban, allokációk adapterekben, nem használt lambda kifejezések. Az ötödik — IPC Jank: folyamatok közötti kommunikáció (ContentProvider, Binder) a fő szálon. A hatodik — Rendering Jank: lassú GPU-renderelés nem optimális shaderek vagy nagy méretű textúrák miatt.

Jank típusaOkJellemző időtartamKeresőeszköz
LayoutrequestLayout, relayout5–30 msPerfetto, Systrace
DrawOverdraw, nehéz drawable3–20 msGPU Profiling
ThreadMain thread blokkolása10–200 msAndroid Studio Profiler
GCGarbage Collection5–15 msMemory Profiler
RenderingGPU terhelés10–50 msGPU Tracer, Xcode GPU

Jank diagnosztizálása Androidban

Androidban a Jank diagnosztizálása a Perfetto rendszernyomkövetéssel kezdődik. A Perfetto rögzíti az összes szál, CPU, GPU és ütemező tevékenységét. A Jank egyértelmű mutatója a Choreographer.doFrame és Choreographer.doCallbacks sorok: ha két egymást követő doFrame hívás közötti intervallum meghaladja a 16.6 ms-ot, a képkocka kimaradt. A Perfetto megmutatja a pontos okot — melyik system call, lock vagy GC okozta a késleltetést. Az Android Studio Profilerben hasonló funkció érhető el a CPU Profileren keresztül.

A Jank automatikus észleléséhez éles környezetben a FrameMetricsAggregator használatos — egy API, amely képkockánként gyűjt statisztikákat és munkamenetenként összesíti. Android 12+-ban megjelent a PerformanceHintManager — egy API a rendszer felé történő célzott képkockasebesség-jelzésekhez. Ha az alkalmazás jelzi, hogy 120 FPS-es forgatókönyvben dolgozik, a rendszer növelheti a CPU/GPU frekvenciát a Jank megelőzése érdekében. Az összes kihagyott képkocka egyszerű naplózásához elegendő feliratkozni a Choreographer.FrameCallback-re.

Jank naplózása Choreographer segítségével

A Kotlin kód feliratkozik a Choreographer.FrameCallback-re és naplóz minden kihagyott képkockát a késleltetés időtartamának megadásával. A callback minden VSync-nél meghívásra kerül.

kotlin
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 képkocka kihagyva")
                }
            }
            previousFrameTime = currentTime
            Choreographer.getInstance()
                .postFrameCallback(this)
        }

    fun start() {
        Choreographer.getInstance()
            .postFrameCallback(callback)
    }
}

Jank diagnosztizálása iOS-ben

iOS-ben a Jank diagnosztizálása az Instruments segítségével történik a Core Animation sablonnal. Az Instruments valós időben mutatja az FPS-t, az offscreen-renderek számát és a hit-testeket. A Jank fő mutatói iOS-ben: piros oszlopok a Core Animation időskáláján (képkocka költségvetésének túllépése), magas Renderer mutató (offscreen renderinget jelent) és alacsony FPS. Az éles környezet monitorozásához a MetricKit jelentéseket gyűjt az MXAnimatoryMetric metrikával, amely magában foglalja az átlagos FPS-t, a P50 és P95 képkockaidőt.

A Jank natív diagnosztizálása iOS-ben magában foglalja a CADisplayLink-et a timestamp és targetTimestamp ellenőrzésével. Ha az aktuális timestamp jelentősen elmarad a targetTimestamp-től, egy vagy több képkocka kimaradt. Az Apple az egyéni profilozáshoz az os_signpost használatát is ajánlja: helyezzen el signpost-intervallumot a képkocka renderelés elején és végén, és ellenőrizze az Instruments-ben, mely intervallumok haladják meg a 16.6 ms-ot. A SwiftUI-ben a Jank diagnosztizálásához a UIView.invalidateIntrinsicContentSize használatos — ennek a metódusnak a gyakori meghívása instabil Layout-ra utal.

CADisplayLink a Jank észleléséhez

A Swift kód a CADisplayLink segítségével határozza meg a kihagyott képkockákat. Ha a timestamp és a targetTimestamp közötti különbség meghaladja a 16.6 ms-ot — a Jank rögzítésre kerül.

swift
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 profilozó eszközök

A Jank profilozásához mind az operációs rendszer beépített eszközeit, mind külső SDK-kat használnak. Androidban a kulcsfontosságú eszköz a Perfetto (felváltotta a Systrace-t). A Perfetto lehetővé teszi akár 30 másodperces nyomkövetések rögzítését és elemzését a ui.perfetto.dev webes felületen keresztül. Pontos idővonalat mutat a Choreographer, a renderelő szálak (RenderThread) és a GPU tevékenységével. A GPU-problémák részletes elemzéséhez az AGI (Android GPU Inspector) használatos, amely nemcsak a képkockaidőt mutatja, hanem a GPU egyes blokkjainak — shaderek, raszterizáló, textúra blokk — terhelését is.

iOS-ben a megfelelő az Instruments a Core Animation, Metal System Trace és GPU Driver sablonokkal. A Core Animation az FPS-t és a képkockaidőt mutatja, a Metal System Trace a GPU munkáját részletezi minden egyes draw call-ig. Valós eszközökön, terhelés alatt történő profilozáshoz a Firebase Performance (Screen Rendering metrikát gyűjt) és a Sentry (stack trace-t rögzít Jank esetén) használatos. Az új Android 15 Performance Hint API lehetővé teszi a fejlesztő számára, hogy jelezze a rendszernek, mely képkockák fontosak, és figyelmeztetéseket kapjon a rendszertől a Jank közeledtekor.

FrameMetricsAggregator éles környezetben

A Kotlin kód a FrameMetricsAggregator-t használja a képkocka-statisztikák munkamenetenkénti gyűjtésére. Az aggregátor leállítása után megjelenik a kihagyott képkockák száma.

kotlin
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 arány: ${jankFrames * 100 / totalFrames}%")
    }
}

A képkocka akadozás megszüntetésének módszerei

A Jank megszüntetése a típustól függő módszerek kombinációját igényli. Layout Jank esetén: a mély hierarchiák cseréje ConstraintLayout/Compose/SwiftUI-ra, merge-tagek használata, requestLayout kerülése animációkban. Draw Jank esetén: Debug GPU Overdraw használata a 4x+ overdraw megtalálásához, nehéz drawable-ok cseréje vektorosra (VectorDrawable/PDF), a hardware layers óvatos használata — gyorsítják a renderelést, de több GPU memóriát fogyasztanak. Thread Jank esetén: az összes I/O művelet, adatbázis-munka és Bitmap dekódolás áthelyezése háttérszálakra, Kotlin Coroutines használata megfelelő Dispatcher-rel vagy RxJava Schedulers.io()-val.

GC Jank esetén: allokációk minimalizálása onDraw()-ban és getView()-ben, objektumpoolok (ObjectPool) használata, for-each cseréje indexelt for-ra, immutable data class óvatos használata Kotlinban a copy()-val — a copy új objektumot hoz létre. IPC Jank esetén: ContentProvider lusta inicializálása App Startup segítségével, Binder-hívások áthelyezése háttérszálra. Rendering Jank esetén: textúrák méretének csökkentése a képernyő maximális felbontására, ASTC vagy ETC2 tömörítés használata, felesleges shader compilation kerülése (shaderek előzetes fordítása). Komplex megoldás — rendszeres Perfetto/Instruments profilozás futtatása CI-ban és a Jank-regressziók nyomon követése.

Anti-Jank minta: Async Layout

A Kotlin kód aszinkron adatbetöltést mutat be a képernyőre a reportFullyDrawn után, hogy a nehéz munka ne blokkolja az első képkockát. A callback akkor hívódik meg, amikor a felhasználó látja a felületet.

kotlin
class JankSafeLoader {

    suspend fun loadAfterFirstFrame(
        activity: Activity
    ) {
        // garantáljuk, hogy az első képkocka már renderelve van
        if (Build.VERSION.SDK_INT >= 29) {
            activity.reportFullyDrawn()
        }

        // nehéz betöltés — az első képkocka után
        withContext(Dispatchers.IO) {
            val data = fetchHeavyData()
            withContext(Dispatchers.Main) {
                updateUI(data)
            }
        }
    }
}

Gyakran ismételt kérdések

Mi az a Jank a mobilalkalmazásokban?

Jank — kihagyott renderelési képkockák, amelyek észrevehető akadozásként vagy rángatózásként jelennek meg az animációban. Akkor keletkezik, amikor a képkocka előkészítési ideje meghaladja az időkeretet (16.6 ms 60 FPS esetén).

Melyek a Jank fő okai?

Layout Jank (gyakori requestLayout), Draw Jank (overdraw), Thread Jank (main thread blokkolása), GC Jank (garbage collection), IPC Jank (Binder-hívások) és Rendering Jank (nehéz shaderek).

Hogyan diagnosztizálható a Jank Androidban?

Használja a Perfetto-t rendszernyomkövetéshez, a GPU Profiling-et a képkockafázisok elemzéséhez és a FrameMetricsAggregator-t az éles környezet monitorozásához. Android Studio-ban — CPU Profiler Deep Java Trace-szel.

Hogyan mérhető a Jank iOS-ben?

A Instruments segítségével a Core Animation vagy Metal System Trace sablonnal. Éles környezethez — MetricKit MXAnimatoryMetric metrikával. Programozottan — CADisplayLink a timestamp és targetTimestamp különbségének ellenőrzésével.

Milyen Jank-százalék számít kritikusnak?

A Google adatai szerint a 3%-nál magasabb Jank-mutató (100 görgetésből 3 akadozást tartalmaz) a negatív értékelések 22%-os növekedéséhez vezet. Célérték — a görgetési munkamenetek kevesebb mint 0.5%-a.

Összegzés

  • Jank — kihagyott képkockák, amelyek látható animációs akadozást okoznak a mobilalkalmazásokban.
  • Fő okok: Layout Jank, Draw Jank, Thread Jank, GC Jank, IPC Jank és Rendering Jank.
  • Jank diagnosztizálása Androidban — Perfetto, GPU Profiling és FrameMetricsAggregator segítségével.
  • Jank diagnosztizálása iOS-ben — Instruments, CADisplayLink és MetricKit segítségével.
  • A Jank megszüntetése kombinációt igényel: lapos hierarchiák, háttérszálak, minimális allokáció, gyorsítótárazás.
  • Cél Jank-mutató — a görgetési munkamenetek kevesebb mint 0.5%-a akadozással.
  • A rendszeres CI-profilozás megakadályozza a teljesítményregressziókat az éles környezetbe kerülés előtt.

Kulcsrakész mobilalkalmazást fejlesztünk

Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.

Projekt megbeszélése

Olvassa el is