Jank pentru aplicațiile mobile — ce este, cauze și eliminare

Autor: IT Sectr Publicat: 2026-04-01 Timp de citire: 10 min

Jank — este un termen care desemnează întârzierile vizibile sau „bâlbâiala” animației interfeței, cauzate de omiterea cadrelor individuale. În aplicațiile mobile, Jank apare atunci când timpul de randare a unui cadru depășește bugetul alocat de rata de reîmprospătare a afișajului. Conform Android Developers, 2025, Jank este cauza principală a senzației subiective de „încetinire” — aplicația poate fi funcțional perfectă, dar utilizatorul o percepe ca fiind lentă din cauza unui FPS instabil.

Principalele puncte

  • Jank — cadre omise, vizibile ca întârzieri ale animației.
  • Cauza principală — depășirea bugetului de timp per cadru (16.6 ms pentru 60 FPS).
  • Jank apare din cauza unui Layout greu, GC lung, blocarea main thread sau overdraw.
  • Pentru diagnosticare se utilizează FrameTimeline (Android) și Instruments (iOS).
  • Eliminarea Jank crește NPS și retenția utilizatorilor cu 15–25%.

Ce este Jank

Jank — este un termen din domeniul graficii computerizate care desemnează un defect vizual în care animația se mișcă sacadat în loc de o alunecare lină. În dezvoltarea mobilă, Jank se măsoară ca numărul de cadre omise (skipped frames) pe unitatea de timp. Dacă sistemul nu reușește să pregătească un cadru până la momentul VSync, afișajul repetă cadrul anterior — apare o pauză de 16.6 ms la 60 Hz. Un cadru omis poate fi imperceptibil, dar o serie de 3–5 cadre omise consecutiv creează o senzație de „încetinire” de 50–80 ms pe care utilizatorul o resimte clar.

Jank este deosebit de critic pentru animațiile care trebuie să ruleze cu viteză constantă: derularea listelor, animația de deschidere a meniului, efectele de paralaxă, tranzițiile între ecrane. Conform unui studiu UX Google (2024), o aplicație cu un indicator Jank de peste 3% din sesiunile de derulare primește cu 22% mai multe recenzii de o stea decât o aplicație cu un indicator sub 0.5%. Instrumentul Android Vitals urmărește automat Jank și îl clasifică după severitate: moderate, severe și critical.

Principalele cauze ale Jank

Cauzele Jank se împart în mai multe categorii. Prima — Layout Jank: cauzat de requestLayout() frecvente din cauza modificării dimensiunilor View, animațiilor LayoutTransition sau încărcării dinamice a conținutului. Fiecare apel requestLayout declanșează Measure + Layout pentru întregul subarbore View, ceea ce poate dura 5–30 ms. A doua — Draw Jank: asociat cu suprasolicitarea (overdraw) și utilizarea drawable-urilor grele. A treia — Thread Jank: blocarea main thread din cauza operațiunilor sincrone — încărcarea fișierelor, lucrul cu baza de date pe firul principal, decodificarea Bitmap.

A patra categorie — GC Jank: garbage collection în ART/Dalvik sau Swift ARC. Când în heap se acumulează multe obiecte, GC declanșează o pauză Stop-The-World de 5–15 ms. Pe Android, pauzele GC apar cel mai frecvent la alocări frecvente în bucle: crearea de obiecte în onDraw(), alocări în adaptoare, expresii lambda neutilizate. A cincea — IPC Jank: comunicarea interproces (ContentProvider, Binder) pe firul principal. A șasea — Rendering Jank: randarea lentă a GPU din cauza shader-elor neoptimale sau a texturilor de dimensiuni mari.

Tip JankCauzăDurată tipicăInstrument de căutare
LayoutrequestLayout, relayout5–30 msPerfetto, Systrace
DrawOverdraw, drawable grele3–20 msGPU Profiling
ThreadBlocarea main thread10–200 msAndroid Studio Profiler
GCGarbage Collection5–15 msMemory Profiler
RenderingÎncărcarea GPU10–50 msGPU Tracer, Xcode GPU

Diagnosticarea Jank în Android

În Android, diagnosticarea Jank începe cu trasarea de sistem Perfetto. Perfetto înregistrează activitatea tuturor firelor, CPU, GPU și a planificatorului. Un indicator clar al Jank sunt liniile Choreographer.doFrame și Choreographer.doCallbacks: dacă intervalul dintre două apeluri consecutive doFrame depășește 16.6 ms, cadrul este omis. Perfetto arată cauza exactă — care system call, lock sau GC a cauzat întârzierea. În Android Studio Profiler, o funcționalitate similară este disponibilă prin CPU Profiler.

Pentru detectarea automată a Jank în producție se utilizează FrameMetricsAggregator — API care colectează statistici pentru fiecare cadru și le agregă pe sesiune. În Android 12+ a apărut PerformanceHintManager — API pentru sugestii către sistem privind rata de cadre țintă. Dacă aplicația indică faptul că rulează într-un scenariu de 120 FPS, sistemul poate crește frecvența CPU/GPU pentru a preveni Jank. Pentru logarea simplă a tuturor cadrelor omise, este suficient să vă abonați la Choreographer.FrameCallback.

Logarea Jank prin Choreographer

Codul în Kotlin se abonează la Choreographer.FrameCallback și loghează fiecare cadru omis cu indicarea duratei întârzierii. Callback-ul este apelat la fiecare 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",
                        "S-au omis $skippedFrames cadre")
                }
            }
            previousFrameTime = currentTime
            Choreographer.getInstance()
                .postFrameCallback(this)
        }

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

Diagnosticarea Jank în iOS

În iOS, diagnosticarea Jank se realizează prin Instruments cu șablonul Core Animation. Instruments arată FPS în timp real, numărul de randări offscreen și hit-test-uri. Principalii indicatori ai Jank în iOS: coloane roșii în scala de timp Core Animation (depășirea bugetului cadrului), indicatorul ridicat Renderer (înseamnă offscreen rendering) și FPS scăzut. Pentru monitorizarea producției, MetricKit colectează rapoarte cu metrica MXAnimatoryMetric, care include FPS mediu, P50 și P95 timpul cadrului.

Diagnosticarea nativă a Jank în iOS include CADisplayLink cu verificarea timestamp și targetTimestamp. Dacă timestamp-ul curent rămâne semnificativ în urma targetTimestamp, înseamnă că unul sau mai multe cadre au fost omise. Apple recomandă, de asemenea, utilizarea os_signpost pentru profilarea personalizată: plasarea signpost-interval la începutul și sfârșitul randării cadrului și verificarea în Instruments care intervale depășesc 16.6 ms. În SwiftUI, pentru diagnosticarea Jank se utilizează UIView.invalidateIntrinsicContentSize — apelarea frecventă a acestei metode indică un Layout instabil.

CADisplayLink pentru detectarea Jank

Codul în Swift determină cadrele omise prin CADisplayLink. Dacă diferența dintre timestamp și targetTimestamp depășește 16.6 ms — Jank este înregistrat.

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

Instrumente de profilare Jank

Pentru profilarea Jank se utilizează atât instrumentele integrate ale sistemului de operare, cât și SDK-uri terțe. În Android, instrumentul cheie este Perfetto (a înlocuit Systrace). Perfetto permite înregistrarea de trace-uri de până la 30 de secunde și analizarea lor prin interfața web ui.perfetto.dev. Acesta arată axa temporală exactă cu activitatea Choreographer, firele de randare (RenderThread) și GPU. Pentru analiza detaliată a problemelor GPU se utilizează AGI (Android GPU Inspector), care arată nu doar timpul cadrului, ci și încărcarea blocurilor specifice GPU — shader-e, rasterizator, blocul de texturi.

În iOS, echivalentul este Instruments cu șabloanele Core Animation, Metal System Trace și GPU Driver. Core Animation arată FPS și timpul cadrului, Metal System Trace — activitatea GPU cu detaliere până la fiecare draw call. Pentru profilarea pe dispozitive reale sub sarcină se utilizează Firebase Performance (colectează metrica Screen Rendering) și Sentry (capturează stack trace la Jank). Noul API Android 15 Performance Hint permite dezvoltatorului să indice sistemului care cadre sunt importante și să primească avertismente de la sistem la apropierea de Jank.

FrameMetricsAggregator în producție

Codul în Kotlin utilizează FrameMetricsAggregator pentru colectarea statisticilor cadrelor pe sesiune. După oprirea agregatorului, se afișează numărul de cadre omise.

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

Metode de eliminare a întârzierilor cadrelor

Eliminarea Jank necesită o combinație de metode în funcție de tipul acestuia. Pentru Layout Jank: înlocuirea ierarhiilor adânci cu ConstraintLayout/Compose/SwiftUI, utilizarea merge-tag-urilor, evitarea requestLayout în animații. Pentru Draw Jank: utilizarea Debug GPU Overdraw pentru găsirea overdraw-ului 4x+, înlocuirea drawable-urilor grele cu vectoriale (VectorDrawable/PDF), utilizarea cu prudență a hardware layers — accelerează randarea, dar consumă mai multă memorie GPU. Pentru Thread Jank: mutarea tuturor operațiunilor I/O, lucrului cu baza de date și decodificării Bitmap pe fire de fundal, utilizarea Kotlin Coroutines cu Dispatcher corespunzător sau RxJava cu Schedulers.io().

Pentru GC Jank: minimizarea alocărilor în onDraw() și getView(), utilizarea pool-urilor de obiecte (ObjectPool), înlocuirea for-each cu for indexat, utilizarea cu grijă a immutable data class în Kotlin cu copy() — copy creează un obiect nou. Pentru IPC Jank: inițializarea lentă a ContentProvider prin App Startup, mutarea apelurilor Binder pe un fir de fundal. Pentru Rendering Jank: reducerea dimensiunii texturilor la rezoluția maximă a ecranului, utilizarea compresiei ASTC sau ETC2, evitarea shader compilation inutile (compilarea shader-elor în avans). Soluția complexă — rularea regulată a profilării Perfetto/Instruments în CI și urmărirea regresiilor Jank.

Model Anti-Jank: Async Layout

Codul Kotlin demonstrează încărcarea asincronă a datelor pe ecran după reportFullyDrawn, pentru ca munca grea să nu blocheze primul cadru. Callback-ul este apelat după ce utilizatorul vede interfața.

kotlin
class JankSafeLoader {

    suspend fun loadAfterFirstFrame(
        activity: Activity
    ) {
        // garantăm că primul cadru este deja randat
        if (Build.VERSION.SDK_INT >= 29) {
            activity.reportFullyDrawn()
        }

        // încărcare grea — după primul cadru
        withContext(Dispatchers.IO) {
            val data = fetchHeavyData()
            withContext(Dispatchers.Main) {
                updateUI(data)
            }
        }
    }
}

Întrebări frecvente

Ce este Jank în aplicațiile mobile?

Jank — sunt cadre de randare omise care se manifestă ca întârzieri vizibile sau sacadări ale animației. Apare atunci când timpul de pregătire a cadrului depășește bugetul de timp (16.6 ms pentru 60 FPS).

Care sunt principalele cauze ale Jank?

Layout Jank (requestLayout frecvente), Draw Jank (overdraw), Thread Jank (blocarea main thread), GC Jank (garbage collection), IPC Jank (apeluri Binder) și Rendering Jank (shader-e grele).

Cum se diagnostichează Jank în Android?

Utilizați Perfetto pentru trace de sistem, GPU Profiling pentru analiza fazelor cadrului și FrameMetricsAggregator pentru monitorizarea producției. În Android Studio — CPU Profiler cu Deep Java Trace.

Cum se măsoară Jank în iOS?

Prin Instruments cu șablonul Core Animation sau Metal System Trace. Pentru producție — MetricKit cu MXAnimatoryMetric. Programatic — CADisplayLink cu verificarea diferenței dintre timestamp și targetTimestamp.

Ce procent de Jank este considerat critic?

Conform Google, un indicator Jank de peste 3% din sesiunile de derulare (3 din 100 de derulări conțin o întârziere) duce la o creștere a recenziilor negative cu 22%. Indicatorul țintă — sub 0.5% din sesiunile de derulare.

Rezumat

  • Jank — cadre omise care cauzează întârzieri vizibile ale animației în aplicațiile mobile.
  • Cauze principale: Layout Jank, Draw Jank, Thread Jank, GC Jank, IPC Jank și Rendering Jank.
  • Diagnosticarea Jank în Android — prin Perfetto, GPU Profiling și FrameMetricsAggregator.
  • Diagnosticarea Jank în iOS — prin Instruments, CADisplayLink și MetricKit.
  • Eliminarea Jank necesită o combinație: ierarhii plate, fire de fundal, minimizarea alocărilor, memorarea în cache.
  • Indicatorul țintă Jank — sub 0.5% din sesiunile de derulare cu întârzieri.
  • Profilarea regulată în CI previne regresiile de performanță înainte de lansarea în producție.

Vom dezvolta o aplicație mobilă la cheie

IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.

Discutați proiectul

Citiți și