Desempenho no desenvolvimento móvel: o que é, quais métricas e como melhorar

Autor: IT Sectr Publicado: 2026-03-25 Tempo de leitura: 12 min

Um aplicativo lento é a principal razão pela qual os usuários desinstalam programas. Milissegundos de atraso na inicialização ou ao rolar uma lista reduzem a retenção em dezenas de por cento. Desempenho (performance) não é apenas velocidade, mas também estabilidade: ausência de ANR, crashes e vazamentos de memória. Este artigo cobre todos os aspectos de desempenho: do gerenciamento de memória (GC, ARC) à criação de perfil com ferramentas. Saiba mais no guia oficial do Android Performance.

Principais pontos

  • ANR e Crash são os principais inimigos da experiência do usuário; prevenidos com threads em segundo plano
  • Vazamento de memória e Retain Cycle levam a crashes OOM; resolvidos com referências fracas e utilitários
  • GC (Android) e ARC (iOS) — modelos de gerenciamento de memória; entender seu funcionamento é crítico
  • Perfilamento (Instruments, Android Profiler, LeakCanary) — etapa obrigatória do desenvolvimento
  • Cold Start — a métrica de inicialização mais importante; otimizar Application.onCreate e inicialização preguiçosa
  • Tamanho do App — usar App Bundle, R8, VectorDrawable e WebP para reduzir o tamanho

Por que o aplicativo está lento?

O desempenho do aplicativo está diretamente ligado ao jank — um atraso perceptível entre a ação do usuário e a resposta da interface. Principais causas: bloqueio da thread principal (operações pesadas na thread de UI), redesenho frequente de layout (overdraw), vazamentos de memória (GC frequente), algoritmos não otimizados (O(n²) em grandes conjuntos de dados). Frame Rate (FPS) — número de quadros por segundo. Para uma experiência confortável, são necessários 60 FPS estáveis (Android) ou 120 FPS (iPhone Pro, iPad Pro). VSync sincroniza a renderização com a taxa de atualização da tela.

O jank ocorre quando a renderização de um único quadro excede 16,6 ms (para 60 FPS) ou 8,3 ms (para 120 FPS). A criação de perfil de GPU (Profile GPU Rendering no Android, Core Animation no iOS) mostra quais estágios de renderização consomem mais tempo. Estágios principais: Layout (posicionamento de elementos), Draw (desenho), Display (transferência para o buffer de quadros). O problema mais comum é a inflação de layout em XML, especialmente com ConstraintLayout aninhados complexos.

Time-to-Interactive (TTI) — tempo que o aplicativo leva para ficar totalmente pronto para interação. O TTI inclui Cold Start, carregamento de dados e inicialização de bibliotecas. O Google recomenda TTI inferior a 5 segundos, a Apple — inferior a 2 segundos para telas principais. Lazy Loading — técnica de carregamento adiado de conteúdo e bibliotecas, crítica para melhorar o TTI. Na IT Sectr, usamos inicialização preguiçosa por padrão em todos os projetos.

ANR e Crash

ANR e Crash são os principais inimigos do desempenho de aplicativos móveis. ANR (Application Not Responding) — caixa de diálogo no Android que aparece se a thread principal estiver bloqueada por mais de 5 segundos. Causas: requisições de rede síncronas na thread de UI, trabalho com banco de dados sem corrotinas, decodificação de bitmap grande sem downsampling, deadlock na thread principal. A pilha de chamadas ANR é salva em /data/anr/traces.txt e permite determinar o local exato do bloqueio.

Crash — encerramento inesperado do aplicativo. No Android — é uma Exception (Java/Kotlin) ou Signal (código nativo). No iOS — NSException ou sinal (EXC_BAD_ACCESS — acesso a memória liberada). Ferramentas de Crash Reporting: Firebase Crashlytics, Sentry, BugSnag. Elas coletam stacktrace, dados do dispositivo e etapas de reprodução. Stack Overflow — estouro da pilha de chamadas por recursão infinita. OutOfMemoryError — quando o heap está cheio.

StrictMode — ferramenta do Android para detectar violações de segurança de threads. Permite definir regras: ThreadPolicy (proibir disco/rede na thread principal), VmPolicy (detectar vazamentos de Activity, SQLite, CloseGuard). StrictMode deve ser ativado apenas em compilações de depuração — na versão de lançamento não deve funcionar. No iOS, o equivalente é o Main Thread Checker (Xcode), que detecta automaticamente chamadas UIKit fora da thread principal.

Gerenciamento de memória (GC, ARC, Retain Cycle)

Vazamento de memória

Um vazamento de memória (Memory Leak) ocorre quando um objeto permanece na memória mesmo que o aplicativo não o utilize mais. Isso reduz diretamente o desempenho do aplicativo. No Android, o GC (Garbage Collection) não pode coletar um objeto se houver uma referência forte a ele. Causas típicas: referências estáticas a Activity, callbacks/observadores não cancelados, classes internas com referência implícita à classe externa, Handler com mensagens não limpas. LeakCanary — biblioteca para detecção automática de vazamentos.

Retain Cycle

ARC (Automatic Reference Counting) — modelo de gerenciamento de memória no iOS. Cada objeto tem um contador de referências (retain count). Quando o contador zera, a memória é liberada. Um Retain Cycle ocorre quando dois objetos mantêm referências fortes entre si (A → B e B → A). O ARC nunca zerará os contadores. Solução: referências fracas (weak) ou sem dono (unowned). Weak é anulado automaticamente (torna-se nil) quando o objeto é liberado. Unowned não é anulado, mas garante que o objeto está vivo.

GC vs ARC

GC (Garbage Collection) funciona no Android (Java/Kotlin). O GC pausa periodicamente a execução (pausa Stop-the-World) para encontrar e liberar objetos inalcançáveis. Gatilho do GC: quando o heap atinge uma certa porcentagem de ocupação. O ARC funciona no iOS (Swift/Objective-C) e não tem pausas — os contadores são atualizados atomicamente a cada atribuição. O ARC é mais previsível, mas pode acumular operações retain/release excessivas sob alta frequência de atribuições.

Referência fraca (Weak Reference) e referência forte (Strong Reference) — o tipo de referência determina se o GC/ARC pode liberar o objeto. Strong Reference — o objeto não será coletado enquanto esta referência existir. Weak Reference — o GC/ARC pode coletar o objeto; a referência fraca torna-se nil (em Swift/Java WeakReference). Unowned Reference (Swift) — não é anulado na liberação; acessá-la após a morte do objeto causa um crash. No Android, usa-se java.lang.ref.WeakReference para referências fracas.

Exemplo de detecção de vazamento no Android usando 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")
    }
}

Perfilamento (Instruments, Android Profiler)

O perfilamento é o processo de medir o desempenho do aplicativo: CPU, memória, rede, consumo de energia. Sem perfilamento, a otimização às cegas é inútil — você não saberá qual parte do código está realmente lenta.

Ferramenta Plataforma Mede Quando usar
Instruments (Time Profiler)iOSCPU, chamadas de função, tempo de execuçãoOtimização de algoritmos, busca de gargalos
Instruments (Allocations)iOSMemória, quantidade de objetos, retain countsBusca de vazamentos e consumo excessivo de memória
Instruments (Leaks)iOSRetain cycles, vazamentos de memóriaVerificação regular antes do lançamento
Android Profiler (CPU)AndroidUso de CPU, atividade de threads, tracesBusca de bloqueios da thread principal
Android Profiler (Memory)AndroidHeap dump, rastreamento de alocaçãoBusca de vazamentos, análise de objetos
Android Profiler (Network)AndroidTráfego, velocidade, tempos de requisiçãoOtimização de chamadas de rede
LeakCanaryAndroidDetecção automática de vazamentos de memóriaEm todas as etapas do desenvolvimento
StrictModeAndroidDisco/rede na thread principal, vazamentosCompilação de depuração
Traceview / SystraceAndroidRastreamento de métodos, eventos do sistemaAnálise profunda de latência

Instruments (Xcode) — a ferramenta mais poderosa para iOS. O Time Profiler mostra quais funções consomem mais CPU. O Allocations rastreia a criação e liberação de objetos. O Leaks encontra automaticamente retain cycles. Etapas do perfilamento: (1) iniciar o Instruments; (2) selecionar o modelo (Time Profiler para CPU); (3) executar o cenário problemático; (4) analisar a pilha de chamadas — a coluna mais larga é a função mais "quente".

O Android Profiler está integrado ao Android Studio (View → Tool Windows → Profiler). O CPU Profiler mostra a carga de cada thread. O Memory Profiler — heap dump e rastreamento de alocação. O Network Profiler — todas as requisições HTTP com tempos. Energy Profiler — consumo de energia: WakeLock, Location, Network. Para rastreamento detalhado, usa-se Systrace (Android 10+) ou Perfetto — rastreamento do sistema com precisão de microssegundos.

Inicialização do app (Cold/Warm/Hot Start)

A inicialização do aplicativo é um dos principais indicadores de desempenho. Ela se divide em três tipos: Cold Start — o aplicativo é iniciado do zero: o processo é criado, Application.onCreate (Android) / AppDelegate.applicationDidFinishLaunching (iOS), carregamento de classes, inicialização de bibliotecas. Warm Start — o processo existe, mas a Activity/ViewController está destruída (por exemplo, ao girar a tela ou retornar da memória). Hot Start — a Activity/ViewController está na memória, o aplicativo é simplesmente exibido (alternância de outro aplicativo).

Cold Start é a métrica mais importante. No Android, inclui: (1) launch Activity — carregamento de XML, inicialização da View; (2) primeiro quadro — tempo até a primeira renderização. O Google recomenda: launch Activity < 200 ms, primeiro quadro < 500 ms, TTI < 5 segundos. Otimização de Cold Start: reduzir Application.onCreate (corrotinas para inicialização preguiçosa), usar SplashScreen API (Android 12+), adiar inicialização de bibliotecas (WorkManager, DI), remover ContentProviders desnecessários.

No iOS, o Cold Start inclui: carregamento do binário Mach-O, dyld (linkeditor dinâmico), inicialização do runtime Objective-C, delegado do aplicativo, primeiro controlador. Chrome Custom Tabs (Android) e Universal Links (iOS) — tecnologias para abrir conteúdo externo rapidamente no aplicativo sem um Cold Start completo. Recomenda-se testar o Cold Start em dispositivos reais de médio porte.

Otimização de tamanho

O tamanho do aplicativo é um fator de desempenho para instalação e atualizações. Ele afeta a conversão: cada 10 MB reduzem a conversão em 1%. O Google Play recomenda tamanho de APK inferior a 150 MB; a App Store — inferior a 200 MB (redes celulares — 100 MB). Principais métodos de otimização: compressão de imagens (WebP em vez de PNG economiza 25-35%), vetorização (VectorDrawable no Android, SF Symbols no iOS), remoção de código não utilizado (R8/ProGuard), remoção de recursos não utilizados (lint → unused resources).

App Bundle (Android) — formato de publicação no qual o Google Play gera um APK otimizado para cada dispositivo. O App Bundle reduz o tamanho do download em 20-40%. Dynamic Delivery — módulos baixados sob demanda (on-demand feature modules). No iOS, o equivalente são os On-Demand Resources (ODR): recursos baixados após a primeira inicialização (níveis de jogo, vídeos).

Lazy Loading — técnica na qual módulos e bibliotecas não são carregados na inicialização, mas sim conforme necessário. Split APK (Android) e App Slicing (iOS) — divisão do aplicativo em segmentos de arquitetura: arm64-v8a, x86_64. Otimização do tamanho do App — um processo contínuo: analise a composição do APK (Analyze APK no Android Studio), remova ícones duplicados, use SVG em vez de várias densidades de PNG. Na IT Sectr, incluímos a verificação do tamanho da compilação no CI/CD para cada MR.

Perguntas frequentes

O que é ANR e como evitá-lo?

ANR (Application Not Responding) — caixa de diálogo que aparece no Android se a thread principal estiver bloqueada por mais de 5 segundos. Para evitar ANR, mova todas as operações pesadas (rede, banco de dados, processamento de arquivos) para threads em segundo plano. O equivalente no iOS é frozen UI, quando o aplicativo para de responder a toques.

O que é um vazamento de memória e um Retain Cycle?

Um vazamento de memória ocorre quando um objeto não pode ser liberado porque ainda existem referências a ele. Um Retain Cycle é uma situação no iOS/Objective-C onde dois objetos se referenciam mutuamente (A → B → A) e o ARC não pode liberar nenhum. Solução: referências weak/unowned e limpeza oportuna de callbacks.

Quais ferramentas usar para perfilamento?

Para iOS: Instruments (Time Profiler, Allocations, Leaks). Para Android: Android Profiler (CPU, Memory, Network), LeakCanary (vazamentos de memória), StrictMode (violações de threads). Recomenda-se combinar o perfilamento durante o desenvolvimento e a integração.

Como o Cold Start difere do Warm Start e do Hot Start?

Cold Start — o aplicativo é iniciado do zero: o processo é criado, as classes são carregadas, o Application.onCreate é executado. Warm Start — o processo existe, mas a Activity/ViewController é recriada. Hot Start — a Activity/ViewController já está na memória, simplesmente exibida. Cold Start é o mais lento (1-5 segundos) e é crítico para a experiência do usuário.

Como reduzir o tamanho de um aplicativo móvel?

Principais métodos: remover recursos e código não utilizados (use R8/ProGuard), vetorizar imagens (VectorDrawable, SF Symbols), comprimir PNG/WebP (Android), usar App Bundle em vez de APK, remover bibliotecas desnecessárias, usar Lazy Loading para módulos. A otimização de tamanho pode reduzir o APK em 40-60%.

Resumo

  • ANR e Crash — os principais problemas de estabilidade; resolvidos com threads em segundo plano e relatórios de crash
  • Vazamento de memória e Retain Cycle — principais causas de OOM; resolvidos com referências fracas e LeakCanary
  • GC (pausas Stop-the-World) vs ARC (sem pausas, mas retain cycles) — modelos de memória diferentes
  • Perfilamento — etapa obrigatória: Instruments (iOS), Android Profiler, LeakCanary, StrictMode
  • Cold Start — métrica chave; otimizar Application.onCreate e inicialização preguiçosa
  • App Bundle e WebP/VectorDrawable — principais ferramentas para reduzir o tamanho em 20-60%
  • Desempenho é um processo contínuo, não uma atividade pontual; integre métricas no CI/CD

Vamos desenvolver um aplicativo móvel chave na mão

A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.

Discutir o projeto