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 profilingLendo 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.0Tempo 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()ouc()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
profvispara exploração; usesummaryRprofpara 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 CIprofvis({...})— 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
- system.time() e proc.time()
- Criação de perfis de código com Rprof e profvis
- Vetorização para obter velocidade
- Avaliação de desempenho com microbenchmark