tracemalloc — 메모리 할당 추적
tracemalloc — 메모리 할당 추적
tracemalloc 모듈은 Python이 할당한 메모리 블록을 추적하는 디버그 도구예요. 다음 정보를 제공해요:
- 객체가 할당된 traceback
- 파일 이름과 줄 번호별 할당된 메모리 블록 통계: 할당된 메모리 블록의 총 크기, 수, 평균 크기
- 메모리 누수를 감지하기 위한 두 스냅샷 간의 차이 계산
Python이 할당한 대부분의 메모리 블록을 추적하려면, PYTHONTRACEMALLOC 환경 변수를 1로 설정하거나 -X tracemalloc 명령줄 옵션을 사용해 가능한 한 빨리 모듈을 시작해야 해요. 런타임에 tracemalloc.start() 함수를 호출해 Python 메모리 할당 추적을 시작할 수도 있어요.
본문
기본적으로 할당된 메모리 블록의 trace는 가장 최근 프레임(1 프레임)만 저장해요. 시작 시 25 프레임을 저장하려면 PYTHONTRACEMALLOC 환경 변수를 25로 설정하거나 -X tracemalloc=25 명령줄 옵션을 사용해요.
예제 (Examples)
상위 10개 표시
메모리를 가장 많이 할당하는 10개 파일 표시:
import tracemalloc
tracemalloc.start()
# ... 애플리케이션 실행 ...
snapshot = tracemalloc.take_snapshot()
top_stats = snapshot.statistics('lineno')
print("[ Top 10 ]")
for stat in top_stats[:10]:
print(stat)
Python 테스트 스위트 출력 예:
[ Top 10 ]
<frozen importlib._bootstrap>:716: size=4855KiB, count=39328, average=126B
...
차이 계산
두 스냅샷을 찍고 차이를 표시해요:
import tracemalloc
tracemalloc.start()
# ... 애플리케이션 시작 ...
snapshot1 = tracemalloc.take_snapshot()
# ... 메모리를 누출하는 함수 호출 ...
snapshot2 = tracemalloc.take_snapshot()
top_stats = snapshot2.compare_to(snapshot1, 'lineno')
print("[ Top 10 differences ]")
for stat in top_stats[:10]:
print(stat)
시스템에 여유 메모리가 적으면 Snapshot.dump() 메서드로 스냅샷을 디스크에 써서 오프라인으로 분석하고, Snapshot.load() 메서드로 다시 로드할 수 있어요.
메모리 블록의 traceback 가져오기
가장 큰 메모리 블록의 traceback을 표시하는 코드:
import tracemalloc
# 25 프레임 저장
tracemalloc.start(25)
# ... 애플리케이션 실행 ...
snapshot = tracemalloc.take_snapshot()
top_stats = snapshot.statistics('traceback')
# 가장 큰 메모리 블록 선택
stat = top_stats[0]
print("%s memory blocks: %.1f KiB" % (stat.count, stat.size / 1024))
for line in stat.traceback.format():
print(line)
꽤 예쁜 상위(top)
메모리를 가장 많이 할당하는 10줄을 꽤 예쁘게 표시하는 코드(특정 파일 무시 포함):
import linecache
import tracemalloc
def display_top(snapshot, key_type='lineno', limit=10):
snapshot = snapshot.filter_traces((
tracemalloc.Filter(False, "<frozen importlib._bootstrap>"),
tracemalloc.Filter(False, "<unknown>"),
))
top_stats = snapshot.statistics(key_type)
...
get_traced_memory()와 reset_peak()를 사용하면 합계 계산 후의 작은 메모리 사용량과 계산 중의 최대 메모리 사용량을 모두 관찰할 수 있어요.
API
함수 (Functions)
- tracemalloc.clear_traces() — Python이 할당한 메모리 블록의 trace를 지워요.
- tracemalloc.get_object_traceback(obj) — Python 객체
obj가 할당된 traceback을 가져와요.Traceback인스턴스 또는, tracemalloc 모듈이 메모리 할당을 추적하지 않거나 객체 할당을 추적하지 않았다면 None을 반환해요. - tracemalloc.get_traceback_limit() — trace의 traceback에 저장되는 최대 프레임 수를 가져와요.
- tracemalloc.get_traced_memory() — tracemalloc 모듈이 추적한 메모리 블록의 현재 크기와 최대 크기를 튜플
(current: int, peak: int)로 가져와요. - tracemalloc.reset_peak() — tracemalloc 모듈이 추적한 메모리 블록의 최대 크기를 현재 크기로 설정해요. 버전 3.9에서 추가되었어요.
- tracemalloc.get_tracemalloc_memory() — 메모리 블록의 trace를 저장하는 데 사용된 tracemalloc 모듈의 메모리 사용량(바이트)을 가져와요.
- tracemalloc.is_tracing() — tracemalloc 모듈이 Python 메모리 할당을 추적 중이면 True, 그렇지 않으면 False.
- tracemalloc.start(nframe: int = 1) — Python 메모리 할당 추적을 시작해요. 수집된 trace의 traceback은
nframe프레임으로 제한돼요. 기본 제한은 1이에요.nframe은 1보다 크거나 같아야 해요. 더 많은 프레임을 저장하면 tracemalloc 모듈의 메모리와 CPU 오버헤드가 증가해요. - tracemalloc.stop() — Python 메모리 할당 추적을 중지해요. 이전에 수집된 모든 trace도 지워요.
- tracemalloc.take_snapshot() — Python이 할당한 메모리 블록의 trace 스냅샷을 찍어 새
Snapshot인스턴스를 반환해요.
DomainFilter
classtracemalloc.DomainFilter(inclusive: bool, domain: int) — 주소 공간(domain)별로 메모리 블록의 trace를 필터링해요. inclusive가 True이면 도메인에 할당된 블록을 일치시키고, False이면 도메인에 할당되지 않은 블록을 일치시켜요.
Filter
classtracemalloc.Filter(inclusive: bool, filename_pattern: str, lineno: int=None, all_frames: bool=False, domain: int=None) — 메모리 블록 trace에 대한 필터예요. filename_pattern의 구문은 fnmatch.fnmatch() 함수를 참고하세요. .pyc 확장자는 .py로 대체돼요.
예:
Filter(True, subprocess.__file__)— subprocess 모듈의 trace만 포함Filter(False, tracemalloc.__file__)— tracemalloc 모듈의 trace 제외Filter(False, "<unknown>")— 빈 traceback 제외
주요 속성: domain, inclusive, lineno, filename_pattern, all_frames.
Frame
classtracemalloc.Frame — traceback의 프레임. Traceback 클래스는 Frame 인스턴스의 시퀀스예요. 속성: filename(str), lineno(int).
Snapshot
classtracemalloc.Snapshot — Python이 할당한 메모리 블록 trace의 스냅샷. take_snapshot() 함수가 스냅샷 인스턴스를 만들어요.
compare_to(old_snapshot: Snapshot, key_type: str, cumulative: bool=False)— 이전 스냅샷과의 차이를 계산해요.dump(filename)— 스냅샷을 파일에 써요.filter_traces(filters)— 필터된 traces 시퀀스로 새 Snapshot 인스턴스를 만들어요.classmethod load(filename)— 파일에서 스냅샷을 로드해요.statistics(key_type: str, cumulative: bool=False)—key_type으로 그룹화된 정렬된 Statistic 인스턴스 목록을 가져와요.key_type은'filename','lineno','traceback'일 수 있어요.cumulative가 True이면 가장 최근 프레임뿐 아니라 trace traceback의 모든 프레임의 크기와 수를 누적해요.traceback_limit— 스냅샷 촬영 시 traceback에 저장된 최대 프레임 수traces— Python이 할당한 모든 메모리 블록의 trace.Trace인스턴스 시퀀스.
Statistic
classtracemalloc.Statistic — 메모리 할당 통계. Snapshot.statistics()가 Statistic 인스턴스 목록을 반환해요. 속성: count(블록 수), size(총 크기 바이트), traceback(할당된 위치).
StatisticDiff
classtracemalloc.StatisticDiff — 이전과 새 Snapshot 인스턴스 간의 메모리 할당 통계 차이. Snapshot.compare_to()가 반환해요. 속성: count, count_diff, size, size_diff, traceback.
Trace
classtracemalloc.Trace — 메모리 블록의 trace. 속성: domain, size, traceback.
Traceback
classtracemalloc.Traceback — 가장 오래된 프레임에서 가장 최근 프레임까지 정렬된 Frame 인스턴스 시퀀스. traceback은 최소 1 프레임을 포함해요. 프레임을 얻지 못하면 줄 번호 0의 파일 이름 "<unknown>"이 사용돼요.
total_nframe— 잘리기 전 traceback을 구성한 총 프레임 수format(limit=None, most_recent_first=False)— traceback을 줄 목록으로 형식화해요.limit이 설정되면 limit이 양수일 때 가장 최근 limit 프레임을, 그렇지 않으면abs(limit)개 가장 오래된 프레임을 형식화해요.most_recent_first가 True이면 가장 최근 프레임이 먼저 반환돼요.