Rprof와 profvis로 코드 프로파일링
스크립트에서 어떤 함수가 가장 많은 시간을 사용하는지 찾습니다.
Rprof와 profvis로 코드 프로파일링은(는) CoddyKit의 무료 R Academy 강의입니다. 이것은 4개 중 2번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 R Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. R Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
프로파일링이란 무엇입니까
시간 측정은 코드가 얼마나 오래 실행되는지 알려 줍니다. 프로파일링은 그 코드 내부에서 시간이 어디에 사용되는지 알려 줍니다. R의 프로파일러는 일정한 간격으로 호출 스택을 표본 추출하여 어떤 함수의 비용이 큰지 통계적으로 보여 줍니다.
주요 도구는 기본 제공되는 Rprof()와 대화형 profvis 패키지입니다.
Rprof() 시작 및 중지
Rprof('output.prof', interval = 0.01)은 프로파일러를 시작합니다. 10밀리초마다 호출 스택의 표본을 파일에 기록합니다. 느린 코드를 실행한 다음 Rprof(NULL)을 호출하여 기록을 중지합니다.
interval 인수는 초 단위의 표본 추출 빈도를 제어합니다. 값이 작을수록 해상도는 높아지지만 출력 파일은 커집니다.
# 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 profilingsummaryRprof()로 결과 읽기
summaryRprof('output.prof')은 프로파일링 파일을 구문 분석하고 두 개의 데이터 프레임이 포함된 리스트를 반환합니다.
- by.self — 각 함수 자체에서 사용한 시간(호출한 함수의 시간 제외)
- by.total — 해당 함수가 호출한 모든 함수의 시간을 포함한 전체 시간
self.pct를 기준으로 정렬하면 시간이 많이 드는 부분을 찾을 수 있습니다.
# 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자체 시간과 전체 시간 비교
프로파일링에서는 자체 시간과 전체 시간의 차이를 이해하는 것이 중요합니다.
- 자체 시간 — 함수가 자체 줄을 실행하는 데 사용한 시간(호출한 함수가 끝나기를 기다린 시간 제외)
- 전체 시간 — 자체 시간과 호출한 모든 함수에서 사용한 시간을 합한 값
전체 시간은 높지만 자체 시간은 낮은 함수가 느린 이유는 자체 로직이 아니라 해당 함수가 호출하는 함수 때문입니다. 호출한 함수를 최적화하고 호출한 쪽의 함수는 최적화하지 마십시오.
# 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
')profvis 소개
profvis는 Rprof()을 감싸고 RStudio 또는 브라우저에서 대화형 HTML 불꽃 그래프를 제공합니다. 원시 summaryRprof() 출력보다 훨씬 쉽게 읽을 수 있습니다.
install.packages('profvis')로 한 번 설치한 다음 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)
# })profvis 불꽃 그래프 읽기
profvis 출력에는 두 개의 패널이 있습니다.
- 불꽃 그래프 — 가로 막대의 너비는 시간을 나타내며, 중첩된 막대는 호출 스택의 깊이를 나타냅니다
- 데이터 표 — 함수와 소스 줄마다 자체 시간과 전체 시간을 정렬하여 볼 수 있습니다
불꽃 그래프 아래쪽의 너비가 넓은 막대는 비용이 가장 큰 호출 함수입니다. 스택이 높을수록 호출 연결이 깊다는 뜻입니다.
# 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
')시간이 많이 드는 부분 식별
profvis 출력을 확인한 후 불꽃 그래프에서 너비가 넓고 자체 시간이 큰 함수를 찾아 시간이 많이 드는 부분을 식별하십시오. R에서 흔한 원인은 다음과 같습니다.
- 요소별 작업을 수행하는 벡터화되지 않은 반복문
- 반복문 안에서
rbind()또는c()를 반복 호출하여 객체를 계속 키우는 작업 - 긴밀한 반복문 안에서 정규 표현식 또는 문자열 구문 분석을 반복하는 작업
# 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
')메모리 할당 프로파일링
Rprof는 memory.profiling = TRUE를 사용하여 메모리 할당도 추적할 수 있습니다. profvis는 시간 측정 패널과 함께 메모리 패널을 표시하므로, 가비지 컬렉션 일시 중지의 주요 원인인 큰 임시 객체를 할당하는 함수를 찾을 수 있습니다.
# 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
')실제 파이프라인 프로파일링
데이터 파이프라인에 프로파일링을 체계적으로 적용하십시오. 전체 파이프라인을 profvis({})로 감싸고, 가장 느린 단계를 찾은 다음 최적화하고, 다시 프로파일링하여 개선되었는지 확인합니다. 절대로 맹목적으로 최적화하지 마십시오.
# 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
')Rprof 표본 추출의 한계
Rprof는 통계적 표본 추출을 사용하므로 매우 빠른 함수(표본 추출 간격보다 빠른 함수)는 나타나지 않을 수 있습니다. 아주 작은 표현식의 미세 벤치마크에는 대신 microbenchmark 패키지를 사용하십시오.
또한 Rprof는 R 인터페이스 아래에서 실행되는 C/C++ 코드는 프로파일링하지 않습니다. R 수준의 호출 스택만 확인할 수 있습니다.
# 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
')R 프로파일링 모범 사례
신뢰할 수 있는 프로파일링 결과를 얻으려면 다음 방법을 따르십시오.
- 현실적인 데이터 크기로 프로파일링합니다 — 작은 입력은 실제 병목을 감춥니다
- 프로파일링 전에 준비 실행을 수행하여 일회성 설정 비용을 제외합니다
- 로드된 패키지의 간섭을 피하도록 깨끗한 R 세션에서 프로파일링합니다
- 탐색에는
profvis를 사용하고, CI 또는 자동화된 보고서에는summaryRprof를 사용합니다
# 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
')빠른 확인: Rprof의 자체 시간과 전체 시간
summaryRprof() 출력에서 함수의 total.pct = 95%이지만 self.pct = 3%입니다. 이것은 무엇을 의미합니까?
프로파일링 도구 요약
R은 두 수준으로 이루어진 프로파일링 도구 모음을 제공합니다.
Rprof('file.prof', interval=0.01)+Rprof(NULL)+summaryRprof()— 기본 제공되며 스크립트에서 사용할 수 있고 CI에 적합합니다profvis({...})— 소스 줄 주석과 메모리 추적 기능을 갖춘 대화형 불꽃 그래프를 제공합니다
올바른 작업 흐름은 항상 다음과 같습니다. 먼저 측정하고, 시간이 가장 많이 드는 부분을 식별하고, 그 부분만 최적화한 다음, 다시 측정하여 개선을 확인합니다.
자주 묻는 질문
“Rprof와 profvis로 코드 프로파일링” 강의는 무료인가요?
네 — “Rprof와 profvis로 코드 프로파일링” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 R Academy 강의 전체를 잠금 해제할 수 있습니다. R Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“Rprof와 profvis로 코드 프로파일링”에서 뭘 배우나요?
스크립트에서 어떤 함수가 가장 많은 시간을 사용하는지 찾습니다. 브라우저에서 직접 실행하는 실습 코드로 R Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
R Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 R Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 2번째 강의입니다.
“Rprof와 profvis로 코드 프로파일링” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 R Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 R Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- system.time()과 proc.time()
- Rprof와 profvis로 코드 프로파일링
- 속도를 위한 벡터화
- microbenchmark로 성능 벤치마킹