Rendimiento en desarrollo móvil: qué es, métricas clave y cómo mejorar

Autor: IT Sectr Publicado: 2026-03-25 Tiempo de lectura: 12 min

Una aplicación lenta es la principal razón por la que los usuarios desinstalan programas. Milisegundos de retraso al iniciar o al hacer scroll en una lista reducen la retención en decenas de por ciento. El rendimiento (performance) no es solo velocidad, sino también estabilidad: ausencia de ANR, cierres inesperados y fugas de memoria. En este artículo analizaremos todos los aspectos del rendimiento: desde la gestión de memoria (GC, ARC) hasta la creación de perfiles con herramientas. Más información en la guía oficial de Android Performance.

Lo más importante

  • ANR y Crash son los principales enemigos de la experiencia de usuario; se previenen con hilos en segundo plano
  • Fuga de memoria y Retain Cycle provocan cierres por OOM; se solucionan con referencias débiles y utilidades
  • GC (Android) y ARC (iOS) son modelos de gestión de memoria; entender su funcionamiento es crítico
  • Perfilado (Instruments, Android Profiler, LeakCanary) es una etapa obligatoria del desarrollo
  • Cold Start es la métrica de inicio más importante; optimizar Application.onCreate e inicialización diferida
  • Tamaño de la App — usar App Bundle, R8, VectorDrawable y WebP para reducir el tamaño

¿Por qué la aplicación va lenta?

El rendimiento de la aplicación está directamente relacionado con el jank — un retraso notable entre la acción del usuario y la reacción de la interfaz. Causas principales: bloqueo del hilo principal (operaciones pesadas en el hilo de UI), redespliegues frecuentes del layout (overdraw), fugas de memoria (GC frecuente), algoritmos no óptimos (O(n²) en grandes conjuntos de datos). Frame Rate (FPS) — número de fotogramas por segundo. Para una experiencia cómoda se necesitan 60 FPS estables (Android) o 120 FPS (iPhone Pro, iPad Pro). VSync sincroniza el renderizado con la frecuencia de actualización de la pantalla.

El jank ocurre cuando el renderizado de un solo fotograma supera los 16.6 ms (para 60 FPS) u 8.3 ms (para 120 FPS). El perfilado de GPU (Profile GPU Rendering en Android, Core Animation en iOS) muestra qué etapas de renderizado consumen más tiempo. Etapas principales: Layout (colocación de elementos), Draw (dibujado), Display (transferencia al búfer de fotogramas). El problema más común es la inflación del layout en XML, especialmente con ConstraintLayout anidados complejos.

Time-to-Interactive (TTI) — tiempo que tarda la aplicación en estar completamente lista para la interacción. El TTI incluye Cold Start, carga de datos e inicialización de bibliotecas. Google recomienda TTI inferior a 5 segundos, Apple — inferior a 2 segundos para las pantallas principales. Lazy Loading — técnica de carga diferida de contenido y bibliotecas, crítica para mejorar el TTI. En IT Sectr aplicamos la inicialización diferida por defecto en todos los proyectos.

ANR y Crash

ANR y Crash son los principales enemigos del rendimiento de las aplicaciones móviles. ANR (Application Not Responding) — cuadro de diálogo en Android que aparece si el hilo principal está bloqueado más de 5 segundos. Causas: solicitudes de red síncronas en el hilo de UI, trabajo con base de datos sin corrutinas, decodificación de bitmap grande sin downsampling, deadlock en el hilo principal. La pila de llamadas ANR se guarda en /data/anr/traces.txt y permite determinar el punto exacto de bloqueo.

Crash — finalización inesperada de la aplicación. En Android — es una Exception (Java/Kotlin) o Signal (código nativo). En iOS — NSException o señal (EXC_BAD_ACCESS — acceso a memoria liberada). Herramientas de Crash Reporting: Firebase Crashlytics, Sentry, BugSnag. Recogen stacktrace, datos del dispositivo y pasos de reproducción. Stack Overflow — desbordamiento de la pila de llamadas por recursión infinita. OutOfMemoryError — cuando el heap está lleno.

StrictMode — herramienta de Android para detectar violaciones de seguridad de hilos. Permite establecer reglas: ThreadPolicy (prohibir disco/red en el hilo principal), VmPolicy (detectar fugas de Activity, SQLite, CloseGuard). Se recomienda activar StrictMode solo en compilaciones de depuración — en la versión de lanzamiento no debe funcionar. En iOS el equivalente es Main Thread Checker (Xcode), que detecta automáticamente llamadas a UIKit fuera del hilo principal.

Gestión de memoria (GC, ARC, Retain Cycle)

Fuga de memoria

Una fuga de memoria (Memory Leak) es una situación en la que un objeto permanece en la memoria aunque la aplicación ya no lo utiliza. Esto reduce directamente el rendimiento de la aplicación. En Android, GC (Garbage Collection) no puede recolectar un objeto si hay una referencia fuerte hacia él. Causas típicas: referencias estáticas a Activity, callbacks/observadores no cancelados, clases internas con referencia implícita a la clase externa, Handler con mensajes no limpiados. LeakCanary — biblioteca para la detección automática de fugas.

Retain Cycle (Ciclo de retención)

ARC (Automatic Reference Counting) — modelo de gestión de memoria en iOS. Cada objeto tiene un contador de referencias (retain count). Al llegar a cero, la memoria se libera. Un Retain Cycle ocurre cuando dos objetos mantienen referencias fuertes entre sí (A → B y B → A). ARC nunca pondrá los contadores a cero. Solución: referencias débiles (weak) o sin dueño (unowned). Weak se anula automáticamente (se vuelve nil) al liberarse el objeto. Unowned no se anula pero garantiza que el objeto está vivo.

GC vs ARC

GC (Garbage Collection) funciona en Android (Java/Kotlin). GC pausa periódicamente la ejecución (pausa Stop-the-World) para buscar y liberar objetos inalcanzables. Activación del GC: cuando el heap se llena hasta cierto porcentaje. ARC funciona en iOS (Swift/Objective-C) y no tiene pausas — los contadores se actualizan atómicamente con cada asignación. ARC es más predecible pero puede acumular operaciones retain/release excesivas con alta frecuencia de asignaciones.

Referencia débil (Weak Reference) y referencia fuerte (Strong Reference) — el tipo de referencia determina si el GC/ARC puede liberar el objeto. Strong Reference — el objeto no será recolectado mientras exista esta referencia. Weak Reference — el GC/ARC puede recolectar el objeto; la referencia débil se vuelve nil (en Swift/Java WeakReference). Unowned Reference (Swift) — no se anula al liberarse; acceder a ella después de la muerte del objeto provoca un crash. En Android se usa java.lang.ref.WeakReference para referencias débiles.

Ejemplo de detección de fugas en Android con LeakCanary:

kotlin
// Утечка: анонимный класс держит ссылку на Activity
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        val handler = object : Handler(Looper.getMainLooper()) {
            override fun handleMessage(msg: Message) {
                // Используем `this@MainActivity`, сохраняя ссылку на Activity
                Log.d("TAG", "Handler received message")
            }
        }
        handler.sendEmptyMessageDelayed(0, 60000)
    }
}

// Исправление: статический Handler + WeakReference
class SafeHandler(activity: MainActivity) : Handler() {
    private val weakActivity =
        WeakReference(activity)

    override fun handleMessage(msg: Message) {
        weakActivity.get() ?: return
        Log.d("TAG", "Handler received message")
    }
}

Perfilado (Instruments, Android Profiler)

El perfilado es el proceso de medir el rendimiento de la aplicación: CPU, memoria, red, consumo de energía. Sin perfilado, la optimización a ciegas es inútil — no sabrá qué parte del código realmente ralentiza.

Herramienta Plataforma Mide Cuándo usarla
Instruments (Time Profiler)iOSCPU, llamadas a funciones, tiempo de ejecuciónOptimización de algoritmos, búsqueda de cuellos de botella
Instruments (Allocations)iOSMemoria, cantidad de objetos, retain countsBúsqueda de fugas y consumo excesivo de memoria
Instruments (Leaks)iOSRetain cycles, fugas de memoriaVerificación regular antes del lanzamiento
Android Profiler (CPU)AndroidUso de CPU, actividad de hilos, tracesBúsqueda de bloqueos del hilo principal
Android Profiler (Memory)AndroidHeap dump, seguimiento de asignacionesBúsqueda de fugas, análisis de objetos
Android Profiler (Network)AndroidTráfico, velocidad, tiempos de solicitudesOptimización de llamadas de red
LeakCanaryAndroidDetección automática de fugas de memoriaEn todas las etapas del desarrollo
StrictModeAndroidDisco/red en hilo principal, fugasCompilación de depuración
Traceview / SystraceAndroidTraza de métodos, eventos del sistemaAnálisis profundo de latencia

Instruments (Xcode) — la herramienta más potente para iOS. Time Profiler muestra qué funciones consumen más CPU. Allocations rastrea la creación y liberación de objetos. Leaks encuentra automáticamente retain cycles. Pasos del perfilado: (1) iniciar Instruments; (2) seleccionar plantilla (Time Profiler para CPU); (3) ejecutar el escenario problemático; (4) analizar la pila de llamadas — la columna más ancha es la función más «caliente».

Android Profiler está integrado en Android Studio (View → Tool Windows → Profiler). CPU Profiler muestra la carga de cada hilo. Memory Profiler proporciona heap dump y seguimiento de asignaciones. Network Profiler muestra todas las solicitudes HTTP con tiempos. Energy Profiler — consumo de energía: WakeLock, Location, Network. Para trazas detalladas se usa Systrace (Android 10+) o Perfetto — trazado del sistema con precisión de microsegundos.

Inicio de la aplicación (Cold/Warm/Hot Start)

El inicio de la aplicación es uno de los indicadores clave de rendimiento. Se divide en tres tipos: Cold Start — la aplicación se inicia desde cero: se crea el proceso, Application.onCreate (Android) / AppDelegate.applicationDidFinishLaunching (iOS), carga de clases, inicialización de bibliotecas. Warm Start — el proceso existe pero la Activity/ViewController está destruida (por ejemplo, al rotar la pantalla o volver de memoria). Hot Start — la Activity/ViewController está en memoria, la aplicación simplemente se muestra (cambio desde otra aplicación).

Cold Start es la métrica más importante. En Android incluye: (1) launch Activity — carga de XML, inicialización de View; (2) primer fotograma — tiempo hasta el primer renderizado. Google recomienda: launch Activity < 200 ms, primer fotograma < 500 ms, TTI < 5 segundos. Optimización de Cold Start: reducir Application.onCreate (corrutinas para inicialización diferida), usar SplashScreen API (Android 12+), diferir la inicialización de bibliotecas (WorkManager, DI), eliminar ContentProviders innecesarios.

En iOS, Cold Start incluye: carga del binario Mach-O, dyld (enlazador dinámico), inicialización del runtime de Objective-C, delegado de aplicación, primer controlador. Chrome Custom Tabs (Android) y Universal Links (iOS) — tecnologías para abrir rápidamente contenido externo en la aplicación sin un Cold Start completo. Se recomienda probar Cold Start en dispositivos reales de gama media.

Optimización del tamaño

El tamaño de la aplicación es un factor de rendimiento para la instalación y las actualizaciones. Afecta a la conversión: cada 10 MB reducen la conversión en un 1%. Google Play recomienda un tamaño de APK inferior a 150 MB; App Store — inferior a 200 MB (redes móviles — 100 MB). Métodos principales de optimización: compresión de imágenes (WebP en lugar de PNG ahorra 25-35%), vectorización (VectorDrawable en Android, SF Symbols en iOS), eliminación de código no utilizado (R8/ProGuard), eliminación de recursos no utilizados (lint → unused resources).

App Bundle (Android) — formato de publicación en el que Google Play genera un APK optimizado para cada dispositivo. App Bundle reduce el tamaño de descarga en 20-40%. Dynamic Delivery — módulos que se descargan bajo demanda (on-demand feature modules). En iOS el equivalente son On-Demand Resources (ODR): recursos que se descargan después del primer inicio (niveles de juego, vídeos).

Lazy Loading — técnica en la que los módulos y bibliotecas no se cargan al inicio sino que se cargan según sea necesario. Split APK (Android) y App Slicing (iOS) — división de la aplicación en segmentos de arquitectura: arm64-v8a, x86_64. Optimización del tamaño de la App — un proceso continuo: analice la composición del APK (Analyze APK en Android Studio), elimine iconos duplicados, use SVG en lugar de varias densidades de PNG. En IT Sectr incluimos la comprobación del tamaño de la compilación en CI/CD para cada MR.

Preguntas frecuentes

¿Qué es ANR y cómo evitarlo?

ANR (Application Not Responding) — cuadro de diálogo que aparece en Android si el hilo principal está bloqueado más de 5 segundos. Para evitar ANR, mueva todas las operaciones pesadas (red, base de datos, procesamiento de archivos) a hilos en segundo plano. El equivalente en iOS es frozen UI, cuando la aplicación deja de responder a los toques.

¿Qué es una fuga de memoria y un Retain Cycle?

Una fuga de memoria ocurre cuando un objeto no puede liberarse porque todavía existen referencias hacia él. Un Retain Cycle es una situación en iOS/Objective-C donde dos objetos se referencian mutuamente (A → B → A) y ARC no puede liberar ninguno. Solución: referencias weak/unowned y limpieza oportuna de callbacks.

¿Qué herramientas usar para el perfilado?

Para iOS: Instruments (Time Profiler, Allocations, Leaks). Para Android: Android Profiler (CPU, Memory, Network), LeakCanary (fugas de memoria), StrictMode (violaciones de hilos). Se recomienda combinar el perfilado durante el desarrollo y la integración.

¿En qué se diferencia Cold Start de Warm Start y Hot Start?

Cold Start — la aplicación se inicia desde cero: se crea el proceso, se cargan las clases, se ejecuta Application.onCreate. Warm Start — el proceso existe pero la Activity/ViewController se recrea. Hot Start — la Activity/ViewController ya está en memoria, solo se muestra. Cold Start es el más lento (1-5 segundos) y es crítico para la experiencia del usuario.

¿Cómo reducir el tamaño de una aplicación móvil?

Métodos principales: eliminar recursos y código no utilizados (use R8/ProGuard), vectorizar imágenes (VectorDrawable, SF Symbols), comprimir PNG/WebP (Android), usar App Bundle en lugar de APK, eliminar bibliotecas innecesarias, usar Lazy Loading para módulos. La optimización del tamaño puede reducir el APK en un 40-60%.

Resumen

  • ANR y Crash — los principales problemas de estabilidad; se solucionan con hilos en segundo plano y reportes de crash
  • Fuga de memoria y Retain Cycle — causas principales de OOM; se solucionan con referencias débiles y LeakCanary
  • GC (pausas Stop-the-World) vs ARC (sin pausas pero con retain cycles) — diferentes modelos de memoria
  • Perfilado — etapa obligatoria: Instruments (iOS), Android Profiler, LeakCanary, StrictMode
  • Cold Start — métrica clave; optimizar Application.onCreate e inicialización diferida
  • App Bundle y WebP/VectorDrawable — herramientas principales para reducir el tamaño en 20-60%
  • El rendimiento es un proceso continuo, no una actividad puntual; integre métricas en CI/CD

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