Jank pro mobilní aplikace — co to je, příčiny a odstranění

Autor: IT Sectr Publikováno: 2026-04-01 Doba čtení: 10 min

Jank — je termín označující znatelné záseky nebo „zadrhávání” animace rozhraní, způsobené vynecháním jednotlivých snímků. V mobilních aplikacích Jank vzniká, když doba renderování snímku překročí rozpočet přidělený obnovovací frekvencí displeje. Podle Android Developers, 2025 je Jank hlavní příčinou subjektivního pocitu „zpomalení” — aplikace může být funkčně perfektní, ale uživatel ji vnímá jako pomalou kvůli nestabilnímu FPS.

Hlavní body

  • Jank — vynechané snímky, patrné jako záseky animace.
  • Hlavní příčina — překročení časového rozpočtu na snímek (16.6 ms pro 60 FPS).
  • Jank vzniká kvůli těžkému Layout, dlouhému GC, blokování main thread nebo overdraw.
  • Pro diagnostiku se používají FrameTimeline (Android) a Instruments (iOS).
  • Odstranění Jank zvyšuje NPS a udržení uživatelů o 15–25%.

Co je Jank

Jank — je termín z oblasti počítačové grafiky označující vizuální vadu, při které se animace pohybuje trhaně místo plynulého klouzání. V mobilním vývoji se Jank měří jako počet vynechaných snímků (skipped frames) za jednotku času. Pokud systém nestihne připravit snímek do okamžiku VSync, displej zopakuje předchozí snímek — vzniká pauza 16.6 ms při 60 Hz. Jeden vynechaný snímek může být nepostřehnutelný, ale série 3–5 po sobě jdoucích vynechaných snímků vytváří pocit „zpomalení” trvající 50–80 ms, který uživatel jasně registruje.

Jank je obzvláště kritický pro animace, které musí pracovat konstantní rychlostí: rolování seznamu, animace otevírání menu, paralaxní efekty, přechody mezi obrazovkami. Podle UX výzkumu Google (2024) získává aplikace s ukazatelem Jank vyšším než 3% rolování o 22% více jednohvězdičkových recenzí než aplikace s ukazatelem nižším než 0.5%. Nástroj Android Vitals automaticky sleduje Jank a klasifikuje jej podle severity: moderate, severe a critical.

Hlavní příčiny Jank

Příčiny Jank se dělí do několika kategorií. První — Layout Jank: způsobený častými requestLayout() kvůli změnám velikostí View, animacím LayoutTransition nebo dynamickému načítání obsahu. Každé volání requestLayout spouští Measure + Layout pro celý podstrom View, což může trvat 5–30 ms. Druhá — Draw Jank: související s overdraw a používáním těžkých drawable. Třetí — Thread Jank: blokování main thread kvůli synchronním operacím — načítání souborů, práce s databází na hlavním vlákně, dekódování Bitmap.

Čtvrtá kategorie — GC Jank: garbage collection v ART/Dalvik nebo Swift ARC. Když se na hromadě nahromadí mnoho objektů, GC spustí Stop-The-World pauzu trvající 5–15 ms. Na Androidu se GC pauzy nejčastěji vyskytují při častých alokacích v cyklech: vytváření objektů v onDraw(), alokace v adaptérech, nepoužívané lambda výrazy. Pátá — IPC Jank: meziprocesová komunikace (ContentProvider, Binder) na hlavním vlákně. Šestá — Rendering Jank: pomalé renderování GPU kvůli neoptimálním shaderům nebo texturám velké velikosti.

Typ JankPříčinaTypická doba trváníNástroj vyhledávání
LayoutrequestLayout, relayout5–30 msPerfetto, Systrace
DrawOverdraw, těžké drawable3–20 msGPU Profiling
ThreadBlokování main thread10–200 msAndroid Studio Profiler
GCGarbage Collection5–15 msMemory Profiler
RenderingZatížení GPU10–50 msGPU Tracer, Xcode GPU

Diagnostika Jank v Androidu

V Androidu začíná diagnostika Jank systémovým trasováním Perfetto. Perfetto zaznamenává aktivitu všech vláken, CPU, GPU a plánovače. Jasným indikátorem Jank jsou řádky Choreographer.doFrame a Choreographer.doCallbacks: pokud interval mezi dvěma po sobě jdoucími voláními doFrame přesáhne 16.6 ms, snímek je vynechán. Perfetto ukazuje přesnou příčinu — který system call, lock nebo GC způsobil zpoždění. V Android Studio Profiler je podobná funkcionalita dostupná přes CPU Profiler.

Pro automatickou detekci Jank v produkci se používá FrameMetricsAggregator — API, které sbírá statistiku pro každý snímek a agreguje za relaci. V Android 12+ se objevil PerformanceHintManager — API pro nápovědy systému o cílové snímkové frekvenci. Pokud aplikace indikuje, že pracuje ve scénáři 120 FPS, systém může zvýšit frekvenci CPU/GPU pro prevenci Jank. Pro jednoduché logování všech vynechaných snímků stačí se přihlásit k odběru Choreographer.FrameCallback.

Logování Jank přes Choreographer

Kód v Kotlin se přihlásí k odběru Choreographer.FrameCallback a loguje každý vynechaný snímek s uvedením doby zpoždění. Callback je volán při každém VSync.

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",
                        "Vynecháno $skippedFrames snímků")
                }
            }
            previousFrameTime = currentTime
            Choreographer.getInstance()
                .postFrameCallback(this)
        }

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

Diagnostika Jank v iOS

V iOS se diagnostika Jank provádí přes Instruments se šablonou Core Animation. Instruments zobrazuje FPS v reálném čase, počet offscreen-renderů a hit-testy. Hlavní indikátory Jank v iOS: červené sloupce na časové ose Core Animation (překročení rozpočtu snímku), vysoký ukazatel Renderer (znamená offscreen rendering) a nízké FPS. Pro monitorování produkce MetricKit sbírá reporty s metrikou MXAnimatoryMetric, která zahrnuje průměrné FPS, P50 a P95 dobu snímku.

Nativní diagnostika Jank v iOS zahrnuje CADisplayLink s kontrolou timestamp a targetTimestamp. Pokud aktuální timestamp výrazně zaostává za targetTimestamp, byl vynechán jeden nebo více snímků. Apple také doporučuje používat os_signpost pro vlastní profilování: umístit signpost-interval na začátek a konec renderování snímku a v Instruments zkontrolovat, které intervaly přesahují 16.6 ms. Ve SwiftUI se pro diagnostiku Jank používá UIView.invalidateIntrinsicContentSize — časté volání této metody svědčí o nestabilním Layout.

CADisplayLink pro detekci Jank

Kód ve Swift určuje vynechané snímky přes CADisplayLink. Pokud rozdíl mezi timestamp a targetTimestamp přesáhne 16.6 ms — Jank je zaznamenán.

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
        }
    }
}

Nástroje pro profilování Jank

Pro profilování Jank se používají jak vestavěné nástroje OS, tak SDK třetích stran. V Androidu je klíčovým nástrojem Perfetto (nahradil Systrace). Perfetto umožňuje nahrávat trasování až 30 sekund a analyzovat je přes webové rozhraní ui.perfetto.dev. Zobrazuje přesnou časovou osu s prací Choreographer, vláken renderování (RenderThread) a GPU. Pro detailní analýzu problémů s GPU se používá AGI (Android GPU Inspector), který ukazuje nejen dobu snímku, ale také zatížení konkrétních bloků GPU — shaderů, rasterizátoru, bloku textur.

V iOS je obdobou Instruments se šablonami Core Animation, Metal System Trace a GPU Driver. Core Animation zobrazuje FPS a dobu snímku, Metal System Trace — práci GPU s detailem až na každý draw call. Pro profilování na reálných zařízeních pod zátěží se používají Firebase Performance (sbírá metriku Screen Rendering) a Sentry (zachycuje stack trace při Jank). Nové API Android 15 Performance Hint umožňuje vývojáři indikovat systému, které snímky jsou důležité, a dostávat od systému varování při přiblížení k Jank.

FrameMetricsAggregator v produkci

Kód v Kotlin používá FrameMetricsAggregator pro sběr statistik snímků za relaci. Po zastavení agregátoru se zobrazí počet vynechaných snímků.

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",
            "Poměr Jank: ${jankFrames * 100 / totalFrames}%")
    }
}

Metody odstranění záseků snímků

Odstranění Jank vyžaduje kombinaci metod v závislosti na jeho typu. Pro Layout Jank: nahrazení hlubokých hierarchií ConstraintLayout/Compose/SwiftUI, použití merge-tagů, vyhýbání se requestLayout v animacích. Pro Draw Jank: použití Debug GPU Overdraw k nalezení 4x+ overdraw, nahrazení těžkých drawable vektorovými (VectorDrawable/PDF), opatrné použití hardware layers — urychlují renderování, ale spotřebovávají více GPU paměti. Pro Thread Jank: přesun všech I/O operací, práce s databází a dekódování Bitmap na vlákna na pozadí, použití Kotlin Coroutines se správným Dispatcher nebo RxJava s Schedulers.io().

Pro GC Jank: minimalizace alokací v onDraw() a getView(), použití objektových poolů (ObjectPool), nahrazení for-each indexovaným for, opatrné použití immutable data class v Kotlin s copy() — copy vytváří nový objekt. Pro IPC Jank: líná inicializace ContentProvider přes App Startup, přesun Binder volání na vlákno na pozadí. Pro Rendering Jank: snížení velikosti textur na maximální rozlišení obrazovky, použití komprese ASTC nebo ETC2, vyhýbání se zbytečné shader compilation (kompilace shaderů předem). Komplexní řešení — pravidelné spouštění profilování Perfetto/Instruments v CI a sledování Jank regresí.

Anti-Jank vzor: Async Layout

Kód v Kotlin demonstruje asynchronní načítání dat na obrazovku po reportFullyDrawn, aby těžká práce neblokovala první snímek. Callback je volán poté, co uživatel vidí rozhraní.

kotlin
class JankSafeLoader {

    suspend fun loadAfterFirstFrame(
        activity: Activity
    ) {
        // garantujeme, že první snímek je již vykreslen
        if (Build.VERSION.SDK_INT >= 29) {
            activity.reportFullyDrawn()
        }

        // těžké načítání — po prvním snímku
        withContext(Dispatchers.IO) {
            val data = fetchHeavyData()
            withContext(Dispatchers.Main) {
                updateUI(data)
            }
        }
    }
}

Často kladené otázky

Co je Jank v mobilních aplikacích?

Jank — jsou vynechané renderovací snímky, které se projevují jako znatelné záseky nebo trhnutí animace. Vzniká, když doba přípravy snímku překročí časový rozpočet (16.6 ms pro 60 FPS).

Jaké jsou hlavní příčiny Jank?

Layout Jank (časté requestLayout), Draw Jank (overdraw), Thread Jank (blokování main thread), GC Jank (garbage collection), IPC Jank (Binder volání) a Rendering Jank (těžké shadery).

Jak diagnostikovat Jank v Androidu?

Použijte Perfetto pro systémové trasování, GPU Profiling pro analýzu fází snímku a FrameMetricsAggregator pro monitorování produkce. V Android Studio — CPU Profiler s Deep Java Trace.

Jak změřit Jank v iOS?

Přes Instruments se šablonou Core Animation nebo Metal System Trace. Pro produkci — MetricKit s MXAnimatoryMetric. Programově — CADisplayLink s kontrolou rozdílu timestamp a targetTimestamp.

Jaké procento Jank je považováno za kritické?

Podle Google, ukazatel Jank vyšší než 3% relací rolování (3 ze 100 rolování obsahuje zásek) vede k nárůstu negativních recenzí o 22%. Cílový ukazatel — méně než 0.5% relací rolování.

Shrnutí

  • Jank — vynechané snímky způsobující viditelné záseky animace v mobilních aplikacích.
  • Hlavní příčiny: Layout Jank, Draw Jank, Thread Jank, GC Jank, IPC Jank a Rendering Jank.
  • Diagnostika Jank v Androidu — přes Perfetto, GPU Profiling a FrameMetricsAggregator.
  • Diagnostika Jank v iOS — přes Instruments, CADisplayLink a MetricKit.
  • Odstranění Jank vyžaduje kombinaci: ploché hierarchie, vlákna na pozadí, minimální alokace, cachování.
  • Cílový ukazatel Jank — méně než 0.5% relací rolování se záseky.
  • Pravidelné profilování v CI zabraňuje regresím výkonu před nasazením do produkce.

Vyvineme mobilní aplikaci na klíč

IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.

Prodiskutovat projekt

Přečtěte si také