Python

profiling.tracing — 결정론적 프로파일러

Added in version 3.15.

소스 코드: Lib/profiling/tracing/


profiling.tracing 모듈은 파이썬 프로그램의 결정론적 프로파일링을 제공합니다. 이 모듈은 모든 함수 호출, 함수 반환 및 예외 이벤트를 모니터링하고 각각에 대한 정확한 타이밍을 기록합니다. 이러한 방식은 정확한 호출 횟수와 프로그램 실행에 대한 완전한 가시성을 제공하므로 개발 및 테스트 시나리오에 이상적입니다.

참고

이 모듈은 하위 호환성을 위해 cProfile 으로도 제공됩니다. cProfile 이라는 이름은 모든 향후 파이썬 버전에서도 계속 작동합니다. 코드베이스에 적합한 가져오기 방식을 선택하여 사용하십시오.

참조용 문구 그대로 유지

결정론적 프로파일링이란 무엇입니까?

결정론적 프로파일링(Deterministic profiling) 은 프로그램 실행 중 발생하는 모든 함수 호출, 함수 반환 및 예외 이벤트를 캡처합니다. 프로파일러는 이러한 이벤트 사이의 정확한 시간 간격을 측정하여 프로그램이 어떻게 동작하는지에 대한 정확한 통계를 제공합니다.

시간이 어디에 소비되는지 추정하기 위해 주기적으로 호출 스택을 샘플링하는 통계적 프로파일링 과 달리, 결정론적 프로파일링은 모든 이벤트를 기록합니다. 이는 통계적 근사치가 아닌 정확한 호출 횟수를 얻을 수 있음을 의미합니다. 대신 모든 이벤트를 계측(instrumenting)하는 과정에서 프로그램 실행 속도를 늦출 수 있는 오버헤드가 발생합니다.

파이썬의 인터프리터 방식은 결정론적 프로파일링을 실용적으로 만들어줍니다. 인터프리터가 이미 함수 호출 및 반환에 대한 이벤트를 배분하므로, 프로파일러는 코드 수정 없이도 이 메커니즘에 훅(hook)을 걸 수 있습니다. 오버헤드는 해석 자체의 비용에 비해 보통 적은 편이어서 결정론적 프로파일링은 대부분의 개발 워크플로우에 적합합니다.

결정론적 프로파일링은 다음과 같은 질문에 답하는 데 도움이 됩니다.

  • 이 함수가 몇 번 호출되었는가?

  • 내 프로그램의 전체 호출 그래프는 무엇인가?

  • 특정 함수에 의해 호출되는 함수들은 무엇인가?

  • 예기치 않은 함수 호출이 발생하고 있는가?

호출 횟수 통계는 버그(의외의 횟수)와 인라인 확장 기회(높은 호출 횟수)를 식별할 수 있습니다. 내부 시간 통계는 최적화가 필요한 “핫 루프(hot loops)”를 드러냅니다. 누적 시간 통제는 알고리즘의 비효율성을 파악하는 데 도움이 됩니다. 이 프로파일러에서 누적 시간을 처리하는 방식은 재귀 구현과 반복 구현을 직접 비교할 수 있게 해줍니다.

명령 줄 인터페이스

profiling.tracing 모듈은 다른 스크립트나 모듈을 프로파일링하기 위해 스크립트로 호출될 수 있습니다.

참조용 문구 그대로 유지

이 명령은 지정된 스크립트 또는 모듈을 프로파일러 하에서 실행하고 그 결과를 표준 출력으로 출력합니다(또는 파일에 저장합니다).

-o <output_file>

프로파일 결과를 표준 출력 대신 파일에 기록합니다. 생성된 결과 파일은 나중에 분석하기 위해 pstats 모듈에서 읽을 수 있습니다.

-s <sort_order>

출력을 지정된 키로 정렬합니다. 이 옵션은 cumulative, time, calls 또는 namepstats.Stats.sort_stats() 에서 인식하는 모든 정렬 키를 허용합니다. 이 옵션은 -o 가 지정되지 않았을 때만 적용됩니다.

-m <module>

스크립트 대신 모듈을 프로파일링합니다. 해당 모듈은 표준 임포트 메커니즘을 통해 위치를 찾습니다.

Added in version 3.7: cProfile``에 대한 ``-m 옵션.

Added in version 3.8: profile`에 대한 `-m`` 옵션.

프로그래밍 방식의 사용 예시

더 세밀한 프로파일링 제어를 원한다면 모듈의 함수와 클래스를 직접 사용하십시오.

기본 프로파일링

가장 간단한 방법은 run() 함수를 사용하는 것입니다.

import profiling.tracing
profiling.tracing.run('my_function()')

이 기능은 주어진 코드 문자열을 프로파일링하고 요약 정보를 표준 출력으로 인쇄합니다. 나중에 분석하기 위해 결과를 저장하려면 다음을 사용하십시오:

profiling.tracing.run('my_function()', 'output.prof')

Profile 클래스 사용

Profile 클래스는 세분화된 제어를 제공합니다:

import profiling.tracing
import pstats
from io import StringIO

pr = profiling.tracing.Profile()
pr.enable()
# ... 프로파일링할 코드 ...
pr.disable()

# 결과 출력
s = StringIO()
ps = pstats.Stats(pr, stream=s).sort_stats(pstats.SortKey.CUMULATIVE)
ps.print_stats()
print(s.getvalue())

Profile 클래스는 컨텍스트 관리자로도 작동합니다:

import profiling.tracing

with profiling.tracing.Profile() as pr:
    # ... 프로파일링할 코드 ...

pr.print_stats()

모듈 참조

profiling.tracing.run(command, filename=None, sort=-1)

명령어의 실행을 프로파일링하고 결과를 인쇄하거나 저장합니다.

이 함수는 __main__ 모듈의 네임스페이스에서 exec() 를 사용하여 command 문자열을 실행합니다:

exec(command, __main__.__dict__, __main__.__dict__)

filename 이 제공되지 않으면, 이 함수는 pstats.Stats 인스턴스를 생성하고 요약 정보를 표준 출력으로 인쇄합니다. filename 이 제공되면 원시 프로파일 데이터가 해당 파일에 저장되어 나중에 pstats 를 사용하여 분석할 수 있습니다.

sort 인수는 출력되는 내용의 정렬 순서를 지정하며, pstats.Stats.sort_stats() 에서 인식하는 모든 값을 허용합니다.

profiling.tracing.runctx(command, globals, locals, filename=None, sort=-1)

명시적인 네임스페이스를 사용하여 명령어의 실행을 프로파일링합니다.

run`과 유사하지만, ``__main__`() 모듈의 네임스페이스를 사용하는 대신 지정된 globalslocals 매핑을 사용하여 명령을 실행합니다:

exec(command, globals, locals)
class profiling.tracing.Profile(timer=None, timeunit=0.0, subcalls=True, builtins=True)

실행 통계를 수집하는 프로파일러 객체입니다.

선택적 timer 인자는 사용자 정의 타이밍 함수를 지정합니다. 제공되지 않으면 프로파일러는 플랫폼에 적합한 기본 타임러를 사용합니다. 사용자 정의 타임러를 제공할 때는 현재 시간을 나타내는 단일 숫자를 반환해야 합니다. 타임러가 정수를 반환하는 경우, timeunit 을 사용하여 한 시간 단위의 지속 시간을 지정하십시오(예를 들어 밀리초의 경우 0.001).

subcalls 인자는 프로파일러가 함수 간의 호출 관계를 추적할지 여부를 제어합니다. builtins 인자는 내장 함수를 프로파일링할지 여부를 제어합니다.

버전 3.8에서 변경: 컨텍스트 관리자 지원을 추가했습니다.

enable()

프로파일링 데이터 수집을 시작합니다.

disable()

프로파일링 데이터 수집을 중지합니다.

create_stats()

데이터 수집을 중지하고 결과를 내부적으로 현재 프로파일로 기록합니다.

print_stats(sort=-1)

현재 프로파일에서 pstats.Stats 객체를 생성하고 결과를 표준 출력으로 인쇄합니다.

sort 인수는 정렬 순서를 지정합니다. 이 인자는 단일 키 또는 다단계 정렬을 위한 키 튜플을 수용하며, pstats.Stats.sort_stats() 와 동일한 값을 사용합니다.

Added in version 3.13: 정렬 키 튜치 지원.

dump_stats(filename)

현재 프로파일 데이터를 filename 에 기록합니다. 해당 파일은 나중에 pstats.Stats 를 사용하여 분석할 수 있습니다.

run(cmd)

exec() 을 통해 명령 문자열을 프로파일링합니다.

runctx(cmd, globals, locals)

지정된 네임스페이스를 사용하여 exec() 를 통해 명령 문자열을 프로파일링합니다.

runcall(func, /, *args, **kwargs)

함수 호출을 프로파일링합니다. func 가 반환하는 값을 그대로 반환합니다:

result = pr.runcall(my_function, arg1, arg2, keyword=value)

참고

프로파일링을 수행하려면 프로파일링 대상 코드가 정상적으로 반환해야 합니다. 프로파일링 중에 인터프리터가 종료되면(예를 들어 sys.exit() 호출 시) 결과를 사용할 수 없습니다.

사용자 정의 타임러 사용

Profile 클래스는 사용자 정의 타이밍 함수를 받아이체벽시계 시간이나 CPU 시간과 같은 실행의 다양한 측면을 측정할 수 있게 합니다. 생성자에 타이밍 함수를 전달하십시오:

pr = profiling.tracing.Profile(my_timer_function)

타임러 함수는 현재 시간을 나타내는 단일 숫자를 반환해야 합니다. 정수를 반환하는 경우, timeunit 을 사용하여 한 단위의 지속 시간을 지정하십시오:

타임러가 밀리초 단위로 시간을 반환함
pr = profiling.tracing.Profile(my_ms_timer, 0.001)

최상의 성능을 위해 타임러 함수는 가능한 한 빠르게 동작해야 합니다. 프로파일러가 이 함수를 빈번하게 호출하므로, 타임러의 오버헤드는 프로파일링 오버헤드에 직접적인 영향을 미칩니다.

time 모듈은 사용자 정의 타임러로 사용하기 적합한 여러 함수를 제공합니다:

제한 사항

결정론적 프로파일링은 시간 정확성과 관련된 내재적인 한계가 있습니다.

기본 타임러는 일반적으로 약 1밀리초의 해상도를 가집니다. 측정값은 이 해상도보다 정확할 수 없습니다. 충분한 횟수의 측정을 통해 시간 오류가 상쇄되는 경향이 있지만, 개별 측정값은 부정확할 수 있습니다.

이벤트 발생 시점과 프로파일러가 타임스탬프를 캡처하는 시점 사이에 지연이 발생합니다. 마찬가지로, 타임스탬프를 읽은 후 사용자 코드가 재개되기 전에도 지연이 발생합니다. 빈번하게 호출되는 함수는 이러한 지연을 누적하며, 이로 인해 실제보다 느리게 보일 수 있습니다. 이 오류는 일반적으로 호출당 한 클록 틱 미만이지만, 여러 번 호출되는 함수의 경우 유의미한 수준이 될 수 있습니다.

profiling.tracing 모듈(및 그 별칭인 cProfile)은 오버헤드가 낮은 C 확장으로 구현되었으므로, 이러한 타이밍 문제는 더 이상 사용되지 않는 순수 파이썬 기반의 profile 모듈보다 덜 두드러집니다.

더 보기

profiling

파이썬 프로파일링 도구 개요 및 적절한 프로파일러 선택 가이드.

profiling.sampling

운영 환경용 통계적 샘플링 프로파일러.

pstats

프로파일 데이터에 대한 통계 분석 및 포맷팅입니다.

profile

더 이상 권장되지 않는 순수 파이썬 프로파일러(보정 관련 문서 포함).

분실물 보관소