FPS en aplicaciones móviles: esencia, cálculo y optimización

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

FPS (Frames Per Second) es una métrica que muestra cuántos fotogramas individuales renderiza un sistema gráfico en un segundo. En el desarrollo móvil, FPS es un indicador estándar de rendimiento de la interfaz de usuario: cuanto más alto es el FPS, más suaves son las animaciones y más receptiva es la interfaz. Según Google Android Performance, 2025, el valor objetivo de FPS para aplicaciones móviles es de 60 fotogramas por segundo, el umbral en el que el ojo humano percibe el movimiento como continuo y fluido.

Puntos clave

  • FPS — cantidad de fotogramas por segundo, la métrica principal de fluidez de la interfaz de usuario.
  • Valor objetivo — 60 FPS, tiempo por fotograma — 16.6 ms.
  • Para pantallas de alta frecuencia de actualización se requieren 120 FPS (8.3 ms por fotograma).
  • La caída de FPS por debajo de 30 es perceptible a simple vista como tirones y retrasos.
  • El monitoreo de FPS en producción ayuda a detectar regresiones de rendimiento.

Qué es FPS

FPS (Frames Per Second) es una unidad de medida de la frecuencia de fotogramas utilizada en gráficos por computadora, video e interfaces móviles. Cada fotograma es una imagen estática que se muestra en la pantalla durante un breve período de tiempo. Con cambios rápidos de fotogramas, el cerebro los percibe como movimiento continuo; este efecto se llama persistencia de la visión. Para las aplicaciones móviles, FPS es una métrica crítica porque cualquier fotograma perdido convierte una animación fluida en un tirón notable. La aplicación debe renderizar cada fotograma estrictamente dentro del presupuesto de tiempo: 16.6 ms para 60 FPS, 11.1 ms para 90 FPS, 8.3 ms para 120 FPS.

FPS se mide no solo para la interfaz de usuario, sino también para juegos, video y cámara. En los juegos, FPS depende de la complejidad de la escena, la calidad de las texturas y la potencia de la GPU. En el video, FPS es fijo (24, 30, 60 fps) y está determinado por el contenido. En las aplicaciones móviles, FPS depende de la eficiencia del código de la interfaz de usuario: complejidad del diseño, cantidad de vistas, frecuencia de redibujado y trabajo del GC (Garbage Collection). Según Apple WWDC 2022, el FPS promedio en una aplicación puede caer entre un 10 y un 15 % debido a actualizaciones ineficientes de colecciones (reloadData en lugar de insert/delete/dequeueReusableCell). Medir FPS en tiempo real es una práctica estándar para los ingenieros de control de calidad y los desarrolladores que trabajan en rendimiento.

Cómo se calcula el FPS

El cálculo del FPS en una aplicación móvil se basa en medir el tiempo entre fotogramas consecutivos. La fórmula más simple: FPS = 1000 / deltaTimeMs, donde deltaTimeMs es el intervalo entre la finalización del fotograma anterior y la finalización del actual. Si el fotograma actual se renderizó en 20 ms, FPS = 1000 / 20 = 50. Sin embargo, en la práctica, el FPS rara vez es estable incluso dentro de un solo segundo: un perfil típico incluye fotogramas de 12 a 16 ms intercalados con fotogramas omitidos (jank) o lentos (40 a 60 ms). Por lo tanto, el FPS se mide como un promedio móvil de 1 a 5 segundos o como percentiles de la distribución del tiempo de fotograma.

En Android, el FPS se calcula mediante Choreographer, que recibe una devolución de llamada de VSync (pulso de sincronización de la pantalla). Cada devolución de llamada corresponde a un fotograma. Si la devolución de llamada no llega, el fotograma se omite. Choreographer permite medir la cantidad exacta de fotogramas por segundo y la cantidad de fotogramas omitidos. En iOS, CADisplayLink funciona de manera similar: se llama cada vez que la pantalla está lista para renderizar un nuevo fotograma. La propiedad timestamp contiene la hora exacta del último fotograma, y targetTimestamp la hora esperada del siguiente. La diferencia entre ellos es el presupuesto de tiempo para el fotograma actual.

Monitoreo de FPS mediante CADisplayLink

El código en Swift demuestra un monitoreo simple de FPS mediante CADisplayLink. El contador frameCount se incrementa con cada llamada, y una vez por segundo se calcula el FPS real.

swift
class FpsCounter {

    private var displayLink: CADisplayLink?
    private var frameCount = 0
    private var lastTime = TimeInterval(0)

    func start() {
        displayLink = CADisplayLink(
            target: self,
            selector: #selector(countFrame)
        )
        displayLink?.add(to: .current,
            forMode: .common)
    }

    @objc
    private func countFrame() {
        frameCount += 1
        let now = Date().timeIntervalSince1970

        if now - lastTime >= 1.0 {
            print("FPS: \(frameCount)")
            frameCount = 0
            lastTime = now
        }
    }
}

Por qué 60 FPS es el estándar

El estándar de 60 FPS (o 60 Hz) se consolidó en la industria por varias razones. La primera es fisiológica: el ojo humano no distingue fotogramas individuales en frecuencias superiores a 50–60 Hz, percibiéndolos como movimiento fluido. Este umbral se denomina Critical Flicker Fusion (CFF). La segunda es histórica: los primeros tubos de rayos catódicos (CRT) funcionaban a 60 Hz en EE. UU. (NTSC) y 50 Hz en Europa (PAL). Las pantallas LCD modernas heredaron esta frecuencia. La tercera es técnica: para las animaciones de la interfaz de usuario, 60 FPS proporciona una latencia de respuesta al tacto de menos de un milisegundo, lo cual es fundamental para la entrada de texto, el desplazamiento y la acción de arrastrar.

Para los desarrolladores móviles, 60 FPS no es solo una recomendación, sino un presupuesto estricto de 16.6 ms por fotograma. Este presupuesto se divide entre todas las fases de renderizado: Entrada (1–2 ms), Animación (2–3 ms), Diseño (3–5 ms), Dibujo (3–5 ms) e Intercambio (1–2 ms). Si alguna fase supera su subpresupuesto, es posible que el fotograma no entre en los 16.6 ms. Google Android Performance recomienda mantenerse dentro de los 12–14 ms para la preparación del fotograma, dejando 2–4 ms de margen para interrupciones del sistema (GC, subprocesos en segundo plano). Según Firebase Performance, las aplicaciones con un FPS promedio inferior a 52 y un P99 FPS inferior a 30 reciben un 35 % más de quejas sobre el rendimiento en las reseñas de Google Play.

FPS y tiempo de fotograma: relación

FPS y tiempo de fotograma son dos caras de la misma métrica, y es importante no confundirlos. FPS es velocidad, el tiempo de fotograma es latencia. A 60 FPS, cada fotograma toma 16.6 ms. A 30 FPS, 33.3 ms. Pero FPS es una métrica no lineal: una caída de 60 a 30 FPS significa que el tiempo de fotograma se duplicó, mientras que una caída de 30 a 20 significa un aumento de 1.5 veces. Por lo tanto, los generadores de perfiles muestran el tiempo de fotograma en lugar de FPS, lo que permite ver los fotogramas problemáticos en lugar de una frecuencia promediada. Por ejemplo, un promedio de 55 FPS puede ocultar el hecho de que el 5 % de los fotogramas tienen un tiempo de fotograma de 50 a 100 ms; estos fotogramas causan Jank pero no afectan significativamente el FPS promedio.

Al analizar el rendimiento, se recomienda observar no el FPS promedio, sino el histograma del tiempo de fotograma. En Android Studio Profiler e iOS Instruments, el tiempo de fotograma se muestra como una escala donde la zona verde es hasta 16.6 ms (60 FPS), la amarilla es de 16.6 a 33.3 ms (30–60 FPS) y la roja es más de 33.3 ms (menos de 30 FPS). Cada columna roja es un retraso notable para el usuario. Una regla práctica: P95 Frame Time (el 95 % de los fotogramas entran en X ms) es una métrica más confiable que el FPS promedio. Si el P95 Frame Time supera los 32 ms (30 FPS), la aplicación se percibe como lenta incluso con un FPS promedio de 50.

Conversión de tiempo de fotograma a FPS

Una función en Kotlin para convertir una matriz de tiempos de fotograma a FPS con percentiles. Devuelve no solo el FPS promedio, sino también P50, P90 y P99 para un análisis detallado.

kotlin
data class FpsReport(
    val average: Float,
    val p50: Float,
    val p90: Float,
    val p99: Float
)

fun List<Long>.toFpsReport(): FpsReport {
    val fpsValues = this.map { ms ->
        if (ms > 0) 1000f / ms else 0f
    }.sorted()

    return FpsReport(
        average = fpsValues.average().toFloat(),
        p50 = fpsValues[fpsValues.size / 2],
        p90 = fpsValues[(fpsValues.size * 90 / 100)],
        p99 = fpsValues[(fpsValues.size * 99 / 100)]
    )
}

FPS alto y nuevas pantallas

Los dispositivos móviles modernos con pantallas de 90, 120 y 144 Hz imponen nuevos requisitos al FPS. Si una aplicación ofrece 60 FPS en una pantalla de 120 Hz, el usuario ve microtirones porque cada segundo ciclo de actualización de la pantalla recibe el mismo fotograma. Para mantener 120 FPS, el presupuesto por fotograma se reduce de 16.6 a 8.3 ms, lo que requiere un código de renderizado dos veces más eficiente. Según los desarrolladores de Android (Google I/O 2023), para lograr 120 FPS estables es necesario: evitar asignaciones en el ciclo de dibujo, minimizar la cantidad de vistas en la jerarquía (menos de 80), abandonar los drawables pesados en favor de VectorDrawable y usar surfaceView para gráficos complejos.

La situación es similar en iOS: el iPhone Pro con ProMotion (120 Hz) requiere el doble de fotogramas, pero el tiempo por fotograma se reduce a la mitad. Apple señala que no todas las animaciones deben funcionar a 120 FPS; Core Animation reduce automáticamente la frecuencia de fotogramas para elementos estáticos o de cambio lento. Sin embargo, el desplazamiento, las animaciones de gestos y las transiciones deben ofrecer 120 FPS para una sensación “sedosa”. Los principales problemas al pasar de 60 a 120 FPS son: mayor consumo de energía (25–40 % para la GPU), calentamiento del dispositivo y limitación térmica (throttling), cuando la frecuencia de fotogramas cae debido al sobrecalentamiento. Se recomienda implementar un mecanismo de respaldo: si el tiempo de fotograma supera constantemente los 8.3 ms, reducir programáticamente la frecuencia de fotogramas objetivo a 60 FPS en lugar de esperar la limitación del sistema.

Conmutador de 60/120 FPS

El código en Java para Android determina si el dispositivo puede admitir 120 FPS y cambia el modo de renderizado. Se utiliza Display.getMode para determinar las frecuencias de actualización admitidas.

java
class FpsModeSwitcher {

    static boolean canDo120Fps(Activity activity) {
        Display display = activity.getWindowManager()
            .getDefaultDisplay();
        for (Display.Mode mode : display.getSupportedModes()) {
            if (mode.getRefreshRate() >= 120f) {
                return true;
            }
        }
        return false;
    }
}

Optimización de FPS en aplicaciones

La optimización del FPS requiere un enfoque sistemático, que comienza con la creación de perfiles y termina con la refactorización de las áreas problemáticas. El primer paso es medir el FPS actual con un generador de perfiles. El segundo paso es encontrar los fotogramas que superan el presupuesto. En Android, esto se puede hacer mediante GPU Profiling o Perfetto. En iOS, mediante Instruments con la plantilla Core Animation. El tercer paso es eliminar las causas: reducir el overdraw, disminuir la profundidad de la jerarquía de vistas, reemplazar la fase de diseño con ConstraintLayout, agregar ViewHolder Recycling y mover los cálculos pesados a un subproceso en segundo plano.

Las optimizaciones específicas de FPS incluyen: Frame Pacing, un mecanismo que distribuye uniformemente el tiempo entre los fotogramas para evitar “ráfagas” de fotogramas rápidos y lentos. En Android, Choreographer.FrameCallback con un intervalo fijo permite implementar Frame Pacing. En iOS, CADisplayLink.preferredFrameRateRange hace lo mismo. El segundo método es Triple Buffering: el sistema usa tres búferes en lugar de dos, lo que permite que la GPU comience a renderizar el siguiente fotograma sin esperar a que se libere el anterior. Android habilita automáticamente Triple Buffering cuando es necesario, pero en iOS el desarrollador puede solicitarlo explícitamente a través de CAMetalLayer. El tercero es Texture Caching: almacenar en caché los mapas de bits en la memoria de la GPU para evitar recargarlos en cada fotograma.

Frame Pacing mediante Choreographer

Un ejemplo en Kotlin demuestra la implementación de Frame Pacing con un intervalo fijo de 16.6 ms. Todas las devoluciones de llamada llegan a un intervalo uniforme, incluso si el sistema se retrasa.

kotlin
class PacedFrameRenderer {

    private val targetDelta = 16_666_666L // 16.6 ms (60 FPS)
    private var lastFrameTime = 0L

    private val frameCallback =
        Choreographer.FrameCallback { frameTimeNanos ->
            val delta = frameTimeNanos - lastFrameTime
            if (delta >= targetDelta) {
                onFrame(delta)
                lastFrameTime = frameTimeNanos
            }
            Choreographer.getInstance()
                .postFrameCallback(this)
        }

    private fun onFrame(delta: Long) {
        // renderizado de fotograma
    }
}

Preguntas frecuentes

Qué FPS se considera cómodo para el usuario?

60 FPS es un nivel cómodo para las aplicaciones móviles. La diferencia entre 60 y 120 FPS solo se nota en pantallas de alta frecuencia de actualización durante animaciones rápidas (desplazamiento, arrastre). Por debajo de 30 FPS, es incómodo.

Cómo se relaciona el FPS con el tiempo de fotograma?

FPS = 1000 / FrameTime (ms). Si el tiempo de fotograma es de 16.6 ms, FPS = 60. Si el tiempo de fotograma es de 33.3 ms, FPS = 30. Se recomienda monitorear el tiempo de fotograma en lugar del FPS, ya que muestra los fotogramas problemáticos.

Por qué cae el FPS al desplazarse?

Al desplazarse, el sistema llama a Layout y Draw para cada nuevo elemento de la lista. Si las vistas son complejas, el diseño no se almacena en caché o se utilizan drawables pesados, el tiempo de fotograma aumenta y el FPS cae. La solución es el reciclaje de ViewHolder y una jerarquía plana.

Cómo medir el FPS en iOS?

Use Instruments con la plantilla Core Animation (muestra el FPS en tiempo real). Para la medición programática, use CADisplayLink con conteo de fotogramas por segundo. Para producción, use MetricKit con la métrica MXAnimatoryMetric.

Qué es Triple Buffering y cómo afecta al FPS?

Triple Buffering usa tres búferes en lugar de dos, lo que permite que la GPU comience a renderizar el siguiente fotograma antes de que se complete el VSync actual. Esto suaviza las cargas máximas y mejora la estabilidad del FPS, pero agrega un fotograma de latencia.

Resumen

  • FPS es la métrica clave para la fluidez de la interfaz, el valor objetivo es de 60 fotogramas por segundo.
  • El tiempo de fotograma es un indicador más preciso que el FPS, especialmente los percentiles P95 y P99.
  • Para pantallas de 120 Hz, se requieren 120 FPS con un presupuesto de 8.3 ms por fotograma.
  • Las principales causas de caída de FPS son el overdraw, la anidación profunda de vistas y las asignaciones en el ciclo de dibujo.
  • Frame Pacing y Triple Buffering ayudan a suavizar la irregularidad del tiempo de fotograma.
  • Perfilado de FPS: mediante GPU Profiling (Android), Instruments Core Animation (iOS), Firebase Performance.
  • El monitoreo del P95 Frame Time en producción es fundamental para detectar regresiones antes de quejas masivas de los usuarios.

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