Jank para aplicaciones móviles — qué es, causas y soluciones

Autor: IT Sectr Publicado: 2026-04-01 Tiempo de lectura: 10 min

Jank es un término que se refiere a tirones notables o “tartamudeos” en la animación de la interfaz causados por la pérdida de fotogramas individuales. En aplicaciones móviles, Jank ocurre cuando el tiempo de renderizado del fotograma supera el presupuesto asignado por la frecuencia de actualización de la pantalla. Según Android Developers, 2025, Jank es la causa principal de la sensación subjetiva de “lentitud”: una aplicación puede ser funcionalmente perfecta, pero el usuario la percibe como lenta debido a un FPS inestable.

Puntos clave

  • Jank — fotogramas perdidos que se manifiestan como tirones en la animación.
  • La causa principal es superar el presupuesto de tiempo por fotograma (16.6 ms para 60 FPS).
  • Jank surge debido a Layout pesado, GC largo, bloqueo del hilo principal o overdraw.
  • Para el diagnóstico se utilizan FrameTimeline (Android) e Instruments (iOS).
  • Eliminar Jank aumenta el NPS y la retención de usuarios en un 15–25%.

Qué es Jank

Jank es un término del ámbito de los gráficos por computadora que designa un defecto visual en el que la animación se mueve a trompicones en lugar de deslizarse suavemente. En el desarrollo móvil, Jank se mide como la cantidad de fotogramas perdidos (skipped frames) por unidad de tiempo. Si el sistema no logra preparar un fotograma para el momento del VSync, la pantalla repite el fotograma anterior: se produce una pausa de 16.6 ms a 60 Hz. Un solo fotograma perdido puede pasar desapercibido, pero una serie de 3 a 5 fotogramas perdidos consecutivos crea una sensación de “tartamudeo” de 50 a 80 ms que el usuario percibe claramente.

Jank es especialmente crítico para animaciones que deben funcionar a velocidad constante: desplazamiento de feeds, animación de apertura de menús, efectos de paralaje, transiciones entre pantallas. Según un estudio de UX de Google (2024), una aplicación con un índice de Jank superior al 3% de las sesiones de desplazamiento recibe un 22% más de reseñas de una estrella que una aplicación con un índice inferior al 0.5%. La herramienta Android Vitals rastrea automáticamente Jank y lo clasifica por gravedad: moderado, severo y crítico.

Principales causas de Jank

Las causas de Jank se dividen en varias categorías. La primera es Layout Jank: causada por llamadas frecuentes a requestLayout() debido a cambios en el tamaño de las Views, animaciones LayoutTransition o carga dinámica de contenido. Cada llamada a requestLayout desencadena Measure + Layout para todo el subárbol de Views, lo que puede ocupar de 5 a 30 ms. La segunda es Draw Jank: relacionada con el overdraw y el uso de drawables pesados. La tercera es Thread Jank: bloqueo del hilo principal debido a operaciones síncronas: carga de archivos, trabajo con la BD en el hilo principal, decodificación de Bitmap.

La cuarta categoría es GC Jank: recolección de basura (Garbage Collection) en ART/Dalvik o Swift ARC. Cuando se acumulan muchos objetos en el montón, el GC inicia una pausa Stop-The-World de 5 a 15 ms. En Android, las pausas de GC ocurren con mayor frecuencia durante asignaciones frecuentes en bucles: creación de objetos en onDraw(), asignación en adaptadores, expresiones lambda no utilizadas. La quinta es IPC Jank: comunicación entre procesos (ContentProvider, Binder) en el hilo principal. La sexta es Rendering Jank: renderizado lento de la GPU debido a sombreadores no óptimos o texturas de gran tamaño.

Tipo de JankCausaDuración típicaHerramienta de detección
LayoutrequestLayout, relayout5–30 msPerfetto, Systrace
DrawOverdraw, drawables pesados3–20 msGPU Profiling
ThreadBloqueo del hilo principal10–200 msAndroid Studio Profiler
GCGarbage Collection5–15 msMemory Profiler
RenderingCarga de GPU10–50 msGPU Tracer, Xcode GPU

Diagnóstico de Jank en Android

En Android, el diagnóstico de Jank comienza con el trazado del sistema Perfetto. Perfetto registra la actividad de todos los hilos, la CPU, la GPU y el planificador. Un indicador evidente de Jank son las líneas Choreographer.doFrame y Choreographer.doCallbacks: si el intervalo entre dos llamadas consecutivas a doFrame supera los 16.6 ms, se ha perdido un fotograma. Perfetto muestra la causa exacta: qué system call, lock o GC provocó el retraso. En Android Studio Profiler, la funcionalidad equivalente está disponible a través de CPU Profiler.

Para la detección automática de Jank en producción se utiliza FrameMetricsAggregator, una API que recopila estadísticas de cada fotograma y las agrega por sesión. En Android 12+ apareció PerformanceHintManager, una API para indicar al sistema la frecuencia de fotogramas objetivo. Si la aplicación indica que funciona en un escenario de 120 FPS, el sistema puede aumentar la frecuencia de CPU/GPU para prevenir Jank. Para un registro simple de todos los fotogramas perdidos, basta con suscribirse a Choreographer.FrameCallback.

Registro de Jank mediante Choreographer

El código en Kotlin se suscribe a Choreographer.FrameCallback y registra cada fotograma perdido indicando la duración del retraso. La devolución de llamada se invoca en cada 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",
                        "Skipped $skippedFrames frames")
                }
            }
            previousFrameTime = currentTime
            Choreographer.getInstance()
                .postFrameCallback(this)
        }

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

Diagnóstico de Jank en iOS

En iOS, el diagnóstico de Jank se realiza mediante Instruments con la plantilla Core Animation. Instruments muestra el FPS en tiempo real, la cantidad de renderizados fuera de pantalla y las pruebas de impacto. Los principales indicadores de Jank en iOS: barras rojas en la escala de tiempo de Core Animation (superación del presupuesto del fotograma), un valor alto de Renderer (indica renderizado fuera de pantalla) y un FPS bajo. Para la monitorización en producción, MetricKit recopila informes con la métrica MXAnimatoryMetric, que incluye el FPS medio, el tiempo de fotograma P50 y P95.

El diagnóstico nativo de Jank en iOS incluye CADisplayLink con comprobación de timestamp y targetTimestamp. Si el timestamp actual está significativamente por detrás del targetTimestamp, significa que se ha perdido uno o varios fotogramas. Apple también recomienda usar os_signpost para el perfilado personalizado: colocar un signpost-interval al inicio y al final del renderizado del fotograma y observar en Instruments qué intervalos superan los 16.6 ms. En SwiftUI, para el diagnóstico de Jank se utiliza UIView.invalidateIntrinsicContentSize: las llamadas frecuentes a este método indican un Layout inestable.

CADisplayLink para la detección de Jank

El código en Swift detecta fotogramas perdidos mediante CADisplayLink. Si la diferencia entre timestamp y targetTimestamp supera los 16.6 ms, se registra un Jank.

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

Herramientas de perfilado de Jank

Para el perfilado de Jank se utilizan tanto herramientas integradas del sistema operativo como SDK de terceros. En Android, la herramienta clave es Perfetto (que sustituyó a Systrace). Perfetto permite grabar trazas de hasta 30 segundos y analizarlas a través de la interfaz web ui.perfetto.dev. Muestra una escala de tiempo precisa con la actividad de Choreographer, los hilos de renderizado (RenderThread) y la GPU. Para el análisis detallado de problemas con la GPU se utiliza AGI (Android GPU Inspector), que muestra no solo el tiempo del fotograma sino también la carga de bloques específicos de la GPU: sombreadores, rasterizador, unidad de texturas.

En iOS, el equivalente es Instruments con las plantillas Core Animation, Metal System Trace y GPU Driver. Core Animation muestra el FPS y el tiempo del fotograma, Metal System Trace muestra el trabajo de la GPU con detalle hasta cada draw call. Para el perfilado en dispositivos reales bajo carga se utilizan Firebase Performance (recopila la métrica Screen Rendering) y Sentry (captura el stack trace en caso de Jank). La nueva API Android 15 Performance Hint permite al desarrollador indicar al sistema qué fotogramas son importantes y recibir advertencias del sistema cuando se aproxima un Jank.

FrameMetricsAggregator en producción

El código en Kotlin utiliza FrameMetricsAggregator para recopilar estadísticas de fotogramas durante una sesión. Tras detener el agregador, se muestra la cantidad de fotogramas perdidos.

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

Métodos para eliminar los tirones de fotogramas

La eliminación de Jank requiere una combinación de técnicas según su tipo. Para Layout Jank: sustituir jerarquías profundas por ConstraintLayout/Compose/SwiftUI, usar etiquetas merge, evitar requestLayout en animaciones. Para Draw Jank: usar Debug GPU Overdraw para localizar overdraw 4x+, sustituir drawables pesados por vectores (VectorDrawable/PDF), usar hardware layers con precaución: aceleran el renderizado pero consumen más memoria de GPU. Para Thread Jank: trasladar todas las operaciones de E/S, trabajo con BD y decodificación de Bitmap a hilos en segundo plano, usar Kotlin Coroutines con el Dispatcher adecuado o RxJava con Schedulers.io().

Para GC Jank: minimizar las asignaciones en onDraw() y getView(), usar pools de objetos (ObjectPool), sustituir for-each por for indexado, usar data class inmutables en Kotlin con copy() con cuidado: copy crea un nuevo objeto. Para IPC Jank: inicializar ContentProvider de forma diferida mediante App Startup, trasladar las llamadas Binder a un hilo en segundo plano. Para Rendering Jank: reducir el tamaño de las texturas a la resolución máxima de la pantalla, usar compresión ASTC o ETC2, evitar compilaciones excesivas de shaders (compilar los shaders con antelación). Una solución integral es la ejecución regular de perfiles Perfetto/Instruments en CI y el seguimiento de regresiones de Jank.

Patrón Anti-Jank: Async Layout

El código en Kotlin demuestra la carga asíncrona de datos en pantalla después de reportFullyDrawn, para que el trabajo pesado no bloquee el primer fotograma. La devolución de llamada se invoca después de que el usuario vea la interfaz.

kotlin
class JankSafeLoader {

    suspend fun loadAfterFirstFrame(
        activity: Activity
    ) {
        // garantizar que el primer fotograma ya está renderizado
        if (Build.VERSION.SDK_INT >= 29) {
            activity.reportFullyDrawn()
        }

        // carga pesada — después del primer fotograma
        withContext(Dispatchers.IO) {
            val data = fetchHeavyData()
            withContext(Dispatchers.Main) {
                updateUI(data)
            }
        }
    }
}

Preguntas frecuentes

¿Qué es Jank en aplicaciones móviles?

Jank son fotogramas de renderizado perdidos que se manifiestan como tirones o sacudidas notables en la animación. Ocurre cuando el tiempo de preparación del fotograma supera el presupuesto de tiempo (16.6 ms para 60 FPS).

¿Cuáles son las principales causas de Jank?

Layout Jank (requestLayout frecuente), Draw Jank (overdraw), Thread Jank (bloqueo del hilo principal), GC Jank (recolección de basura), IPC Jank (llamadas Binder) y Rendering Jank (sombreadores pesados).

¿Cómo diagnosticar Jank en Android?

Use Perfetto para el trazado del sistema, GPU Profiling para el análisis de las fases del fotograma y FrameMetricsAggregator para la monitorización en producción. En Android Studio — CPU Profiler con Deep Java Trace.

¿Cómo medir Jank en iOS?

Mediante Instruments con la plantilla Core Animation o Metal System Trace. Para producción — MetricKit con MXAnimatoryMetric. Programáticamente — CADisplayLink comprobando la diferencia entre timestamp y targetTimestamp.

¿Qué porcentaje de Jank se considera crítico?

Según Google, un índice de Jank superior al 3% de las sesiones de desplazamiento (3 de cada 100 desplazamientos contienen un tirón) provoca un aumento del 22% en las reseñas negativas. El índice objetivo es inferior al 0.5% de las sesiones de desplazamiento.

Resumen

  • Jank — fotogramas perdidos que causan tirones visibles en la animación de aplicaciones móviles.
  • Principales causas: Layout Jank, Draw Jank, Thread Jank, GC Jank, IPC Jank y Rendering Jank.
  • Diagnóstico de Jank en Android — mediante Perfetto, GPU Profiling y FrameMetricsAggregator.
  • Diagnóstico de Jank en iOS — mediante Instruments, CADisplayLink y MetricKit.
  • Eliminar Jank requiere una combinación de: jerarquías planas, hilos en segundo plano, asignaciones minimizadas, almacenamiento en caché.
  • Índice objetivo de Jank — menos del 0.5% de sesiones de desplazamiento con tirones.
  • El perfilado regular en CI previene regresiones de rendimiento antes de que lleguen a producción.

Desarrollaremos una aplicación móvil llave en mano

IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.

Discutir el proyecto

Lea también