-
[Python] 파이썬 프로파일링: 성능 병목 현상 찾는 방법언어/파이썬 & 장고 2026. 4. 7. 23:25
📌 이 문서는 Real Python - Profiling in Python 및 추가 웹 검색을 바탕으로 정리되었습니다.
개요
소프트웨어 프로파일링이란 실행 중인 프로그램의 다양한 메트릭을 수집·분석하여 성능 병목 지점을 찾는 과정입니다.
주요 병목 원인:
- 과도한 메모리 사용
- 비효율적인 CPU 활용
- 부최적의 데이터 배치로 인한 캐시 미스
"Make it work, then make it beautiful, then if you really, really have to, make it fast."
언제 최적화할 것인가?
최적화는 반드시 다음 순서로 진행해야 합니다:
- Testing — 코드가 올바르게 작동하는지 검증
- Refactoring — 유지보수성과 파이썬스러움 개선
- Profiling — 비효율적인 부분 식별 후 최적화
⚠️ 2024년 개발자 조사에 따르면, 파이썬 개발자의 47%가 프로파일링 없이 최적화를 시도하며, 그 중 2/3는 아무 효과가 없거나 오히려 성능이 악화되었습니다.
주요 프로파일링 도구
1.
time모듈 — 기본 측정📦 분류: Python 표준 라이브러리 — 별도 설치 없이 바로 사용 가능합니다.
import time t1 = time.perf_counter() function() t2 = time.perf_counter() print(f"실행 시간: {t2 - t1:.2f}초")- 실제 경과 시간(wall-clock time)과 CPU 시간 측정
- I/O 바운드와 CPU 바운드 작업 구분 가능
- 설정이 간단하지만 외부 노이즈 영향을 받음
2.
timeit모듈 — 정확한 벤치마킹📦 분류: Python 표준 라이브러리 — 별도 설치 없이 바로 사용 가능합니다.
from timeit import timeit total_time = timeit("fib(30)", number=100, globals=globals()) average = total_time / 100- 가비지 컬렉션을 비활성화한 상태로 반복 실행
- 시스템 노이즈 최소화
- 짧은 코드 스니펫 벤치마킹에 최적
3.
cProfile— 결정론적 프로파일러📦 분류: Python 표준 라이브러리 —
cProfile과pstats모두 내장 모듈로, 별도 설치 없이 바로 사용 가능합니다.from cProfile import Profile from pstats import Stats, SortKey with Profile() as profile: fib(35) Stats(profile).strip_dirs().sort_stats(SortKey.CALLS).print_stats()수집 정보:
- 함수 호출 횟수
- 함수별 실행 시간
- 재귀 호출 통계
장점 단점 모든 함수 호출 추적으로 정확함 높은 오버헤드 (약 15.4%) 표준 라이브러리 내장 결과가 복잡하고 해석이 어려울 수 있음
4.
Pyinstrument— 통계적 프로파일러📦 분류: 외부 라이브러리 — pip로 설치 후 import하여 사용합니다.
pip install pyinstrumentfrom pyinstrument import Profilerfrom pyinstrument import Profiler with Profiler(interval=0.1) as profiler: estimate_pi(n=10_000_000) profiler.print() profiler.open_in_browser() # 인터랙티브 웹 보고서- 일정한 간격으로 콜 스택 스냅샷 촬영
- 낮은 오버헤드 (간격 조정 가능)
- 시각적 계층 구조로 결과 표시
- 웹 브라우저에서 인터랙티브 보고서 확인 가능
- ⚠️ 멀티스레드와 C 확장 모듈 분석에 제약 있음
5.
Linux perf— 고급 하드웨어 프로파일러 (Python 3.12+)📦 분류: Linux 시스템 도구 — pip 패키지가 아닙니다. OS 패키지 매니저로 설치하며, Python 코드에 import가 필요 없습니다.
# Ubuntu/Debian sudo apt-get install linux-tools-common linux-tools-generic # CentOS/RHEL sudo yum install perfsudo perf record -g -F 999 \ "$HOME/python-custom-build/bin/python3" -X perf script.py sudo perf report --hierarchy --sort comm,dso,sample- 하드웨어 성능 카운터 접근
- CPU 사이클, 캐시 미스, 메모리 대역폭 측정
- C 라이브러리와 Linux 커널 수준 분석
- 최소 오버헤드
병목 현상을 쉽게 찾는 방법 (추가 도구)
line_profiler— 라인별 CPU 분석 (가장 직관적)📦 분류: 외부 라이브러리 — pip로 설치 필요.
@profile데코레이터는kernprof로 실행 시 자동으로 주입되므로 별도 import가 불필요합니다.pip install line-profiler# @profile 데코레이터로 분석할 함수 지정 @profile def slow_function(): result = [] for i in range(10000): result.append(i ** 2) return resultkernprof -l -v script.py- 각 줄의 실행 시간을 상세히 표시
- 어느 라인이 병목인지 바로 확인 가능
- CPU 병목 원인 찾기에 가장 직관적인 도구
py-spy— 프로덕션 환경용 프로파일러📦 분류: 외부 라이브러리 (CLI 도구) — pip로 설치 후 터미널에서 직접 실행합니다. Python 코드에 import가 필요 없습니다.
pip install py-spypy-spy record -o profile.svg -- python script.py py-spy top -- pid 12345 # 실행 중인 프로세스 실시간 분석- 오버헤드 단 2.1% (cProfile 대비 약 7배 낮음)
- 실행 중인 Python 프로세스에 attach 가능
- 스레드 분석 지원
- Flame Graph 출력
Scalene— CPU + 메모리 통합 분석📦 분류: 외부 라이브러리 (CLI 도구) — pip로 설치 후 터미널에서 직접 실행합니다. Python 코드에 import가 필요 없습니다.
pip install scalenescalene script.py- CPU, GPU, 메모리 사용량을 라인별로 동시 측정
- Python 코드와 네이티브 C 코드 구분 분석
- 2023년 이후 가장 주목받는 프로파일러 중 하나
- 메모리 누수 탐지에도 효과적
memory_profiler— 메모리 사용량 분석📦 분류: 외부 라이브러리 — 설치:
pip install memory-profiler/ import:from memory_profiler import profile@profile def memory_heavy_function(): data = [i for i in range(1000000)] return data- 라인별 메모리 사용량 추적
- 메모리 누수 탐지
VizTracer— 시각화 중심 프로파일러📦 분류: 외부 라이브러리 (CLI 도구) — pip로 설치 후 터미널에서 직접 실행합니다. Python 코드에 import가 필요 없습니다.
pip install viztracerviztracer script.py vizviewer result.json- 직관적인 결과 분석 UI
gprof2dot를 통한 시각화로 병목 지점 한눈에 파악- 타임라인 기반으로 실행 흐름 분석
프로파일러 비교표
도구 방식 오버헤드 정확도 사용 난이도 주요 용도 time타이머 낮음 중간 쉬움 간단한 측정 timeit타이머 낮음 높음 쉬움 코드 스니펫 벤치마킹 cProfile결정론적 높음 (15.4%) 매우 높음 중간 전체 함수 호출 분석 Pyinstrument통계적 중간 중간 중간 콜 스택 시각화 line_profiler결정론적 중간 높음 쉬움 라인별 CPU 분석 py-spy통계적 매우 낮음 (2.1%) 높음 중간 프로덕션 환경 Scalene통계적 낮음 높음 쉬움 CPU + 메모리 통합 memory_profiler결정론적 높음 높음 쉬움 메모리 누수 탐지 perf통계적 매우 낮음 높음 어려움 하드웨어 레벨 분석
병목 현상 카테고리
Python 성능 이슈는 주로 다음 5가지 범주에 속합니다:
카테고리 비중 해결 방법 CPU 바운드 연산 35% 알고리즘 개선, NumPy, Cython I/O 대기 시간 25% 비동기 처리 (asyncio) 메모리 할당 20% 제너레이터, 메모리 풀 비효율적인 알고리즘 15% 자료구조 및 알고리즘 교체 외부 의존성 5% 캐싱, 배치 처리
실전 병목 찾기 프로세스
단계별 접근법
- 1단계:
cProfile로 전체 개요 파악- 어떤 함수가 가장 많이 호출되는지 확인
- 전체 실행 시간의 80%를 차지하는 함수 식별
- 2단계:
line_profiler로 해당 함수 라인별 분석- 정확히 어느 라인이 느린지 파악
- 3단계: 최적화 적용
- 메모이제이션, 알고리즘 교체, 데이터 구조 변경 등
- 4단계: 검증
timeit으로 개선 전후 비교
파레토 원칙 활용
코드의 20%를 최적화하면 성능의 80%를 향상시킬 수 있습니다.
실전 예제: 피보나치 최적화
비효율적인 코드
def fib(n): return n if n < 2 else fib(n - 2) + fib(n - 1) # fib(35) 계산: 약 29,860,712 함수 호출 → 9.6초문제: 동일한 값을 반복 계산하는 중복 호출 발생
최적화: 메모이제이션 적용
from functools import lru_cache @lru_cache(maxsize=None) def fib(n): return n if n < 2 else fib(n - 2) + fib(n - 1) # fib(35) 계산: 69번 호출 → 0.0001초 미만
도구 선택 가이드
- 빠른 확인이 필요할 때 →
time,timeit - 전체 함수 호출 분석 →
cProfile - 라인별 CPU 병목 찾기 →
line_profiler⭐ 가장 직관적 - 메모리 누수 탐지 →
memory_profiler,Scalene - 프로덕션 환경 (낮은 오버헤드) →
py-spy,Pyinstrument - CPU + 메모리 동시 분석 →
Scalene⭐ 2025년 추천 - 시각화가 필요할 때 →
VizTracer,Pyinstrument - 하드웨어 레벨 분석 →
perf(Python 3.12+, Linux)
참고 자료
- Real Python: Profiling in Python — How to Find Performance Bottlenecks
- Top 7 Python Profiling Tools for Performance
- Performance Profiling with Py-Spy (2025)
- Python Performance: Profiling and Optimization Techniques
- 파이썬 코드를 프로파일링하는 여러가지 방법 (wikidocs)
- Hyperconnect Tech Blog: 고성능 ML 백엔드를 위한 Python 성능 최적화 팁