0Pricing
R Academy · Aula

Criação de perfis de código com Rprof e profvis

Identifique quais funções consomem mais tempo em seus scripts.

Criação de perfis de código com Rprof e profvis é uma aula grátis de R Academy no CoddyKit. Esta é a aula 2 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de R Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de R Academy inclui 4 aulas no total.

O que é criação de perfil?

A cronometragem informa quanto tempo o código leva para ser executado. A criação de perfil informa onde o tempo é gasto dentro desse código. O criador de perfil do R coleta amostras da pilha de chamadas em intervalos regulares para formar uma visão estatística de quais funções são mais dispendiosas.

As duas ferramentas principais são Rprof(), integrada, e o pacote interativo profvis.

Iniciando e interrompendo Rprof()

Rprof('output.prof', interval = 0.01) inicia o criador de perfil. Ele grava amostras da pilha de chamadas em um arquivo a cada 10 ms. Execute o código lento e, em seguida, chame Rprof(NULL) para interromper a gravação.

O argumento interval controla a frequência de amostragem em segundos — valores menores oferecem mais resolução, mas geram arquivos de saída maiores.

# Pattern — do not run Rprof inside knitr/Quarto
# Rprof('my_profile.prof', interval = 0.01)
#
# slow_function <- function(n) {
#   x <- numeric(n)
#   for (i in seq_len(n)) x[i] <- sqrt(i)
#   sum(x)
# }
# slow_function(500000)
#
# Rprof(NULL)  # stop profiling

Lendo resultados com summaryRprof()

summaryRprof('output.prof') analisa o arquivo de criação de perfil e retorna uma lista com dois quadros de dados:

  • by.self — tempo gasto na própria função (excluindo as funções chamadas)
  • by.total — tempo total, incluindo todas as funções chamadas por essa função

Ordene por self.pct para encontrar os pontos críticos.

# After Rprof() run:
# prof <- summaryRprof('my_profile.prof')
# head(prof$by.self)
#
# Example output columns:
#            self.time self.pct total.time total.pct
# slow_fn        1.22     61.0       1.98      99.0
# sqrt           0.76     38.0       0.76      38.0
# sum            0.02      1.0       0.02       1.0

Tempo próprio versus tempo total

Entender o tempo próprio e o tempo total é fundamental para a criação de perfil:

  • Tempo próprio — tempo que a função gastou executando suas próprias linhas (sem aguardar as funções chamadas)
  • Tempo total — tempo próprio mais todo o tempo gasto nas funções chamadas

Uma função com tempo total alto, mas tempo próprio baixo, é lenta por causa do que ela chama, não da própria lógica. Otimize a função chamada, não a função chamadora.

# Conceptual example:
# wrapper() -> process_data() -> slow_sort()
#
# total.pct: wrapper=100, process_data=90, slow_sort=85
# self.pct:  wrapper=5,   process_data=5,  slow_sort=85
#
# => slow_sort is the real bottleneck to fix.
cat('High total + low self => the culprit is a callee function
')

Apresentando profvis

profvis encapsula Rprof() e fornece um gráfico de chamas HTML interativo no RStudio ou em um navegador. Ele é muito mais fácil de ler do que a saída bruta de summaryRprof().

Instale-o uma vez com install.packages('profvis') e, em seguida, envolva seu código com profvis({...}).

# library(profvis)
#
# profvis({
#   n <- 200000
#   x <- numeric(n)
#   for (i in seq_len(n)) x[i] <- log(i)
#   total <- sum(x)
#   sorted <- sort(x)
# })

Lendo o gráfico de chamas do profvis

A saída do profvis tem dois painéis:

  • Gráfico de chamas — barras horizontais cuja largura = tempo; barras aninhadas = profundidade da pilha de chamadas
  • Tabela de dados — visualização ordenável do tempo próprio e total por função e linha de origem

Barras largas na parte inferior do gráfico de chamas representam as funções chamadoras mais dispendiosas. Pilhas altas indicam cadeias profundas de chamadas.

# Reading the flame graph:
# - Each horizontal bar = one function on the call stack
# - Width proportional to time spent
# - Bottom = outermost caller, top = deepest callee
# - Click a bar to zoom in
# - 'Memory' tab shows allocation by line
cat('profvis shows self time per source line — invaluable for tight loops
')

Identificando pontos críticos

Depois de visualizar a saída do profvis, identifique os pontos críticos procurando funções que sejam largas no gráfico de chamas e tenham tempo próprio elevado. Causas comuns em R:

  • Loops não vetorizados que executam operações elemento a elemento
  • rbind() ou c() repetidos, aumentando objetos dentro de um loop
  • Análise repetida de expressões regulares ou de textos em loops intensivos
# Before fix — growing vector in loop (common hot spot)
# profvis reveals repeated reallocations:
# result <- c()
# for (i in 1:50000) result <- c(result, i^2)
#
# After fix — pre-allocated:
# result <- numeric(50000)
# for (i in 1:50000) result[i] <- i^2
cat('Pre-allocation eliminates the most common loop hot spot
')

Analisando alocações de memória

Rprof também pode rastrear alocações de memória com memory.profiling = TRUE. O profvis mostra um painel de memória ao lado da cronometragem, permitindo identificar funções que alocam objetos temporários grandes — uma fonte importante de pausas na coleta de lixo.

# Memory profiling with Rprof:
# Rprof('mem.prof', interval = 0.01, memory.profiling = TRUE)
# ... slow code ...
# Rprof(NULL)
# prof <- summaryRprof('mem.prof', memory = 'both')
# head(prof$by.self)
#
# profvis also shows mem delta per line automatically
cat('Memory profiling pinpoints allocation hot spots causing GC pauses
')

Criando o perfil de um pipeline real

Aplique a criação de perfil sistematicamente a um pipeline de dados: envolva todo o pipeline em profvis({}), identifique a etapa mais lenta, otimize-a e, em seguida, crie o perfil novamente para confirmar a melhoria. Nunca otimize às cegas.

# Workflow:
# 1. profvis({ full_pipeline() })   => identify Stage 3 is 80% of time
# 2. Rewrite Stage 3 (vectorize / use data.table)
# 3. profvis({ full_pipeline() })   => confirm Stage 3 now < 10%
# 4. system.time({ full_pipeline() }) => confirm overall speedup
cat('Profile -> identify -> fix -> re-profile is the correct cycle
')

Limitações da amostragem de Rprof

Rprof usa amostragem estatística, portanto funções muito rápidas (mais rápidas que o intervalo de amostragem) podem não aparecer. Para microcomparações de expressões pequenas, use o pacote microbenchmark.

Além disso, Rprof não cria o perfil do código C/C++ abaixo da interface R — apenas as pilhas de chamadas no nível R ficam visíveis.

# Rprof interval = 0.01s => functions faster than 10ms may not appear
# For sub-millisecond work use microbenchmark:
#   microbenchmark(expr1, expr2, times = 1000L)
#
# For C-level profiling use external tools:
#   - Instruments (macOS)
#   - perf (Linux)
cat('Rprof is for R-level profiling; use microbenchmark for micro-timing
')

Práticas recomendadas para criação de perfil em R

Siga estas práticas para obter resultados confiáveis:

  • Crie o perfil com tamanhos de dados realistas — entradas pequenas ocultam o verdadeiro gargalo
  • Execute iterações de aquecimento antes da criação de perfil para excluir custos de configuração inicial
  • Crie o perfil em uma sessão R limpa para evitar interferências de pacotes carregados
  • Use profvis para exploração; use summaryRprof para relatórios de CI/automatizados
# Clean session profiling checklist:
# 1. Restart R (Ctrl+Shift+F10 in RStudio)
# 2. Load only required packages
# 3. Run once to warm up
# 4. profvis({ ... })  on second run
# 5. Compare before/after with system.time()
cat('Always profile with realistic data in a clean R session
')

Verificação rápida: próprio versus total em Rprof

Uma função mostra total.pct = 95%, mas self.pct = 3% na saída de summaryRprof(). O que isso indica?

Recapitulação das ferramentas de criação de perfil

R oferece um conjunto de ferramentas de criação de perfil em dois níveis:

  • Rprof('file.prof', interval=0.01) + Rprof(NULL) + summaryRprof() — integrado, utilizável em scripts e adequado para CI
  • profvis({...}) — gráfico de chamas interativo com anotações das linhas de origem e rastreamento de memória

O fluxo de trabalho correto é sempre: medir primeiro, identificar o ponto mais crítico, otimizar somente esse ponto e medir novamente para confirmar o ganho.

Perguntas Frequentes

A aula “Criação de perfis de código com Rprof e profvis” é grátis?

Sim — o texto completo de “Criação de perfis de código com Rprof e profvis” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de R Academy, atualize para CoddyKit PRO. O curso de R Academy inclui 4 aulas no total.

O que vou aprender em “Criação de perfis de código com Rprof e profvis”?

Identifique quais funções consomem mais tempo em seus scripts. Você pratica R Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar R Academy?

Nenhuma experiência prévia é necessária. R Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 2 de 4.

Quanto tempo leva a aula “Criação de perfis de código com Rprof e profvis”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de R Academy?

Sim. Cada aula de R Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. system.time() e proc.time()
  2. Criação de perfis de código com Rprof e profvis
  3. Vetorização para obter velocidade
  4. Avaliação de desempenho com microbenchmark
← Voltar para R Academy