---
title: "Baseline Profiles no Android com Kotlin em 2026 | Kotlin Brasil"
url: "https://kotlin.dev.br/blog/baseline-profiles-macrobenchmark-android-kotlin-2026/"
markdown_url: "https://kotlin.dev.br/blog/baseline-profiles-macrobenchmark-android-kotlin-2026.MD"
description: "Aprenda a usar Baseline Profiles, Macrobenchmark e Jetpack Compose para acelerar startup, navegação e renderização em apps Android Kotlin."
date: "2026-06-05"
author: "Karina Melo"
---

# Baseline Profiles no Android com Kotlin em 2026 | Kotlin Brasil

Aprenda a usar Baseline Profiles, Macrobenchmark e Jetpack Compose para acelerar startup, navegação e renderização em apps Android Kotlin.


Performance Android deixou de ser apenas uma preocupação de times grandes. Em 2026, qualquer app Kotlin que disputa atenção na Play Store precisa abrir rápido, responder sem engasgos e manter a primeira experiência previsível mesmo em celulares intermediários. O usuário não sabe se a lentidão vem do cold start, do carregamento de classes, do primeiro frame do Compose ou de uma tela pesada demais. Ele só sente que o app parece amador.

É nesse ponto que **Baseline Profiles** e **Macrobenchmark** entram no fluxo de desenvolvimento Android moderno. Baseline Profile é uma forma de dizer ao Android quais caminhos de código são importantes para compilar e otimizar antes do usuário tocar no app pela primeira vez. Macrobenchmark é a ferramenta que mede esse impacto em cenários reais: startup, scroll, navegação, troca de tela, renderização e jank. Juntas, essas duas peças transformam performance em algo testável, versionado e revisável em pull request.

Se você já acompanha nossos guias de [Android com Kotlin](/guias/guia-kotlin-android-desenvolvimento/), [Jetpack Compose](/guias/guia-jetpack-compose/), [testes Android com Compose e Maestro](/guias/testes-android-compose-maestro/) e [acessibilidade no Android](/blog/acessibilidade-android-compose-kotlin-2026/), este artigo é o próximo passo: tratar performance como parte do produto, não como uma otimização tardia feita na véspera do lançamento.

## O que é Baseline Profile?

Baseline Profile é um arquivo gerado a partir de fluxos importantes do app. Ele contém uma lista de classes e métodos que o Android Runtime deve priorizar na compilação ahead-of-time ou just-in-time otimizada. Na prática, o app chega ao usuário com caminhos críticos mais preparados para execução rápida.

Sem profile, o Android ainda otimiza o app com o tempo, mas a primeira sessão pode sofrer. O problema é justamente a primeira sessão: onboarding, login, tela inicial, busca, carrinho, feed ou qualquer fluxo que precisa convencer o usuário a continuar. Em apps Compose, isso também ajuda porque a primeira composição de telas complexas pode carregar bastante código do runtime, Material, navegação, imagens, ViewModels e camadas de dados.

Baseline Profile não substitui arquitetura, cache ou UI leve. Ele não corrige uma tela que faz chamada de rede no main thread, não resolve recomposição infinita e não transforma uma consulta lenta em rápida. A vantagem é outra: reduzir o custo inicial de executar caminhos que já são importantes e bem definidos.

## Quando vale investir nisso?

Baseline Profiles fazem mais sentido quando o app já tem uma base mínima de qualidade e precisa melhorar experiência real. Alguns sinais comuns:

- cold start perceptivelmente lento;
- primeira navegação para tela inicial demora;
- tela Compose principal engasga na primeira renderização;
- app tem muitos módulos, bibliotecas ou inicializadores;
- time quer medir performance antes e depois de mudanças;
- app já usa CI/CD e consegue rodar testes instrumentados em device ou emulator controlado.

Se o projeto ainda está quebrando por falta de testes básicos, comece pelo [guia de testes Kotlin](/guias/guia-testes-kotlin/) e por fluxos críticos automatizados. Mas se o app já tem uma trilha confiável de build, Baseline Profile é uma melhoria de alto retorno.

## Estrutura mínima de módulos

O setup moderno costuma ter pelo menos três partes:

1. módulo do app, por exemplo `:app`;
2. módulo de benchmark, por exemplo `:benchmark`;
3. testes que geram profile e medem cenários críticos.

No Gradle Kotlin DSL, o módulo de benchmark usa plugins Android específicos. A configuração exata muda com versões do Android Gradle Plugin, então trate o exemplo como ponto de partida:

```kotlin
plugins {
    id("com.android.test")
    id("org.jetbrains.kotlin.android")
    id("androidx.baselineprofile")
}

android {
    namespace = "br.dev.kotlin.benchmark"
    compileSdk = 36

    defaultConfig {
        minSdk = 28
        targetProjectPath = ":app"
        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
    }
}

dependencies {
    implementation("androidx.test.ext:junit:1.2.1")
    implementation("androidx.test.espresso:espresso-core:3.6.1")
    implementation("androidx.benchmark:benchmark-macro-junit4:1.3.4")
}
```

No módulo do app, o plugin de baseline profile conecta o artefato gerado ao build final:

```kotlin
plugins {
    id("com.android.application")
    id("org.jetbrains.kotlin.android")
    id("androidx.baselineprofile")
}

dependencies {
    baselineProfile(project(":benchmark"))
}
```

A parte importante não é decorar versões. É entender que profile precisa ser gerado por fluxos reais e depois empacotado com o app. Sem isso, o benchmark vira apenas um teste isolado.

## Gerando um Baseline Profile simples

Um teste de geração de profile deve abrir o app e percorrer os caminhos mais valiosos. Para um app de conteúdo, pode ser abrir home, entrar em artigo e voltar. Para e-commerce, home, busca, produto e carrinho. Para banco, login simulado, saldo e extrato. O exemplo abaixo mostra a ideia:

```kotlin
@RunWith(AndroidJUnit4::class)
class BaselineProfileGenerator {
    @get:Rule
    val baselineProfileRule = BaselineProfileRule()

    @Test
    fun gerarProfilePrincipal() {
        baselineProfileRule.collect(
            packageName = "br.dev.kotlin.app",
        ) {
            pressHome()
            startActivityAndWait()

            device.waitForIdle()
            device.findObject(By.text("Entrar")).click()
            device.waitForIdle()

            device.findObject(By.text("Explorar artigos")).click()
            device.waitForIdle()

            device.findObject(By.textContains("Kotlin")).click()
            device.waitForIdle()
        }
    }
}
```

Esse teste usa UI Automator porque o objetivo é simular uso real pelo sistema, não testar uma função interna. Ele deve ser estável, curto e representativo. Um profile gigante com fluxos aleatórios é difícil de revisar e pode esconder problemas. Prefira começar com o caminho que mais afeta retenção: abrir app e chegar na primeira tela útil.

## Medindo startup com Macrobenchmark

Depois de gerar profile, você precisa provar que ele ajudou. Macrobenchmark mede cenários no dispositivo, com controle sobre compilação, iterações e métricas. Para startup, um teste típico fica assim:

```kotlin
@RunWith(AndroidJUnit4::class)
class StartupBenchmark {
    @get:Rule
    val benchmarkRule = MacrobenchmarkRule()

    @Test
    fun coldStartup() = benchmarkRule.measureRepeated(
        packageName = "br.dev.kotlin.app",
        metrics = listOf(StartupTimingMetric()),
        iterations = 10,
        startupMode = StartupMode.COLD,
        compilationMode = CompilationMode.Partial(
            baselineProfileMode = BaselineProfileMode.Require,
        ),
        setupBlock = {
            pressHome()
        },
    ) {
        startActivityAndWait()
    }
}
```

O teste mede tempo de startup em várias iterações. `BaselineProfileMode.Require` força o teste a falhar se o profile esperado não estiver presente, evitando uma conclusão falsa. Em CI, isso protege contra regressões em configuração.

Também vale medir sem profile em uma rodada local para entender o ganho. Mas não misture os resultados de qualquer jeito: emulator, device físico, versão do Android, carga da máquina e modo de compilação mudam bastante os números. O valor do benchmark está mais em comparar mudanças controladas do que em perseguir um número absoluto bonito.

## Medindo jank em telas Compose

Startup é só uma parte. Apps Android modernos sofrem muito com scroll travado, listas pesadas e recomposição desnecessária. Macrobenchmark pode medir frames enquanto o teste interage com a tela:

```kotlin
@RunWith(AndroidJUnit4::class)
class FeedBenchmark {
    @get:Rule
    val benchmarkRule = MacrobenchmarkRule()

    @Test
    fun scrollFeedPrincipal() = benchmarkRule.measureRepeated(
        packageName = "br.dev.kotlin.app",
        metrics = listOf(FrameTimingMetric()),
        iterations = 5,
        startupMode = StartupMode.WARM,
        compilationMode = CompilationMode.Partial(
            baselineProfileMode = BaselineProfileMode.UseIfAvailable,
        ),
    ) {
        startActivityAndWait()
        device.waitForIdle()

        val lista = device.findObject(By.res("feed_list"))
        repeat(5) {
            lista.fling(Direction.DOWN)
            device.waitForIdle()
        }
    }
}
```

Para isso funcionar bem, suas telas precisam ter identificadores estáveis. Em Compose, exponha `testTag` quando fizer sentido:

```kotlin
LazyColumn(
    modifier = Modifier.testTag("feed_list"),
) {
    items(artigos, key = { it.id }) { artigo ->
        ArtigoCard(artigo = artigo)
    }
}
```

A mesma disciplina que ajuda testes de UI ajuda benchmarks. Elementos identificáveis tornam automação mais confiável. Chaves estáveis em listas reduzem recomposição errada. Estados bem separados facilitam investigar gargalo.

## Checklist de performance antes do profile

Baseline Profile potencializa um app saudável. Antes de culpar o runtime, revise pontos simples:

- inicialização preguiçosa para SDKs que não precisam rodar no `Application.onCreate`;
- chamadas de rede e banco fora do main thread;
- imagens redimensionadas e carregadas com cache;
- `LazyColumn` com `key` estável em listas dinâmicas;
- `remember` e `derivedStateOf` usados apenas onde realmente ajudam;
- ViewModels sem trabalho pesado no construtor;
- navegação sem recriar grafo inteiro a cada recomposição;
- logs verbosos desativados em release;
- dependências antigas removidas do startup path.

Depois disso, Baseline Profile reduz custo de execução dos caminhos críticos. Antes disso, ele pode mascarar sintomas sem corrigir a causa.

## Como encaixar no CI/CD

Rodar Macrobenchmark em todo commit pode ser caro. Uma estratégia prática é separar três níveis:

1. testes unitários e de ViewModel em todo pull request;
2. testes instrumentados essenciais em branches principais;
3. Macrobenchmark e geração de Baseline Profile em agenda diária, release candidate ou mudanças que mexem em startup, navegação e UI.

Em projetos com GitHub Actions, Bitrise, GitLab CI ou runners próprios, use um device/emulator consistente e salve artefatos de benchmark. O objetivo é enxergar tendência. Se o cold start subiu 20% depois de adicionar um SDK de analytics, o time precisa saber antes do deploy.

Também vale criar uma regra social: mudança que adiciona inicializador, dependência global, tela inicial nova ou lista pesada precisa olhar benchmark. Performance vira critério de revisão, igual cobertura de teste e acessibilidade.

## Erros comuns

O primeiro erro é gerar profile navegando por fluxos que ninguém usa. Profile deve refletir negócio: login, home, compra, busca, leitura, upload, checkout, reprodução, ou outro caminho que sustenta retenção.

O segundo erro é rodar benchmark em ambiente instável e discutir milissegundos como se fossem verdade absoluta. Compare cenários iguais, use várias iterações e olhe tendência.

O terceiro erro é achar que Baseline Profile resolve toda performance. Se o app trava porque a tela faz processamento pesado durante recomposição, o profile só torna parte do código mais rápida. A arquitetura ainda precisa melhorar.

O quarto erro é esquecer a experiência acessível. Um app pode abrir rápido e ainda ser ruim para quem usa TalkBack, fonte grande ou navegação por teclado. Performance, testes e acessibilidade precisam andar juntos, especialmente em times Android profissionais.

## Um fluxo recomendado para times Kotlin

Para um time que quer começar sem exagero, eu seguiria este caminho:

1. escolha um device ou emulator padrão para medições;
2. crie módulo `:benchmark`;
3. gere Baseline Profile para cold start e primeira navegação útil;
4. adicione um benchmark de startup;
5. adicione um benchmark de scroll da tela mais importante;
6. rode localmente antes de releases;
7. automatize em CI quando o fluxo estiver estável;
8. registre resultados em cada mudança relevante.

Esse fluxo combina bem com uma base Kotlin moderna: Gradle Kotlin DSL, módulos separados, Compose, coroutines, testes com Turbine e boas práticas de arquitetura. Para quem trabalha com produto Android no Brasil, esse tipo de maturidade técnica diferencia uma candidatura de desenvolvedor pleno/sênior e ajuda empresas a reduzir reclamações invisíveis de usuários.

## Conclusão

Baseline Profiles e Macrobenchmark colocam performance Android em um lugar mais saudável: medição antes de opinião. Com Kotlin e Compose, é fácil criar telas ricas, mas também é fácil acumular custo de startup, recomposição e navegação sem perceber. Um profile bem escolhido acelera os caminhos críticos. Um benchmark bem escrito mostra se a mudança realmente ajudou.

Comece pequeno: cold start, home e a tela que mais importa para o negócio. Depois expanda para scroll, navegação e fluxos de conversão. O objetivo não é ganhar uma competição de milissegundos; é entregar um app que parece rápido desde a primeira sessão, em aparelhos reais, para usuários reais.

Para complementar o estudo, revise também [WorkManager com Kotlin no Android](/blog/workmanager-kotlin-android-2026/), [Paging 3 com Kotlin e Compose](/blog/paging-3-kotlin-compose-2026/) e [segurança de dados locais no Android](/blog/seguranca-dados-locais-android-kotlin-2026/). Performance fica mais fácil quando arquitetura, dados, testes e experiência de usuário foram pensados como um sistema só. Se você trabalha com apps de produção, vale acompanhar também o ecossistema Android em sites irmãos como [Python Brasil](https://python.dev.br/?utm_source=kotlin.dev.br&utm_medium=referral&utm_campaign=baseline_profiles_android_kotlin_2026), especialmente para comparar práticas de CI, métricas e automação entre stacks.
