Python cProfile과 Pstat을 이용해 프로파일링 하기

햄도·2021년 1월 8일
0

파이썬에서 많은 양의 데이터를 다루다 보면, 처리 속도가 너무 느리다고 느껴질 때가 있다. 속도가 느린 원인도 다양하고, 해결 방법도 다양하지만 원인을 파악해서 해결하려면 프로그램의 어느 부분이 느린지 먼저 파악해야 한다.

실제로 분석해보면, 느릴 거라고 예상했던 부분이 빠르고 빠를 거라고 장담했던 부분이 느린 경우가 많다. cProfile이란 내장 모듈이 있다는 것을 알기 전에는 부끄럽게도 느릴 거라 예상되는 부분에 time 모듈을 이용해 시간을 측정해 로그를 찍었다.. 그렇게 원시적인 방법으로 나만의 프로파일링을 하다가, 이펙티브 파이썬에서 프로파일링 모듈이 있다는 것을 알게 되었다.

프로파일링 모듈에도 cProfile과 profile 두 가지가 있는데, cProfile은 C 확장 모듈로 프로파일링 동안 프로그램의 성능에 미치는 영향을 최소화할 수 있어 더 좋다고 한다.

기본적인 사용법은 아래와 같다.

import cProfile
import re
cProfile.run('re.compile("foo|bar")')

위 코드를 실행하면 re.compile()이 수행되고, 아래와 같이 결과를 출력한다.

      197 function calls (192 primitive calls) in 0.002 seconds

Ordered by: standard name

ncalls  tottime  percall  cumtime  percall filename:lineno(function)
     1    0.000    0.000    0.001    0.001 <string>:1(<module>)
     1    0.000    0.000    0.001    0.001 re.py:212(compile)
     1    0.000    0.000    0.001    0.001 re.py:268(_compile)
     1    0.000    0.000    0.000    0.000 sre_compile.py:172(_compile_charset)
     1    0.000    0.000    0.000    0.000 sre_compile.py:201(_optimize_charset)
     4    0.000    0.000    0.000    0.000 sre_compile.py:25(_identityfunction)
   3/1    0.000    0.000    0.000    0.000 sre_compile.py:33(_compile)

  • ncalls: 프로파일링 주기 동안 함수 호출 횟수
  • tottime: 함수가 실행되는 동안 소비한 초 단위 시간, 다른 함수 호출 시간은 배제
  • tottime percall: 함수를 호출하는 데 걸린 평균 시간. tottime / ncalls
  • cumtime: 함수를 실행하는 데 걸린 초 단위 누적 시간, 다른 함수 호출 시간 포함
  • cumtime percall: 함수를 호출할 때마다 걸린 시간에 대한 초 단위 평균 시간. cumtime / ncalls

위 예시처럼 바로 모듈에서 제공하는 run() 함수를 이용해 프로파일링을 수행할 수도 있고, 더 세밀한 제어가 필요한 경우에는 cProfile.Profile 클래스를 이용할 수 있다.

명령행 인터페이스로도 사용할 수 있다. 나는 명령행 인터페이스로 실행되는 프로그램을 프로파일링하기 위해 아래와 같이 사용했다.

python -m cProfile -o profile_output train_words.py --dim 100 --method skipgram

-o 옵션을 지정하면 수행 결과가 지정한 파일(profile_output)에 바이너리 형태로 저장된다. train_words.py에 필요한 인자들은 그대로 넣어주면 된다. 그리고 저장된 결과를 확인하려면 아래 코드를 실행한다. 프로파일링 결과 파일은 말했듯이 바이너리 형태이므로 pstats를 이용해야 확인할 수 있다.

stream = open('profile_output_text', 'w')
stats = pstats.Stats('profile_output', stream=stream)
stats.sort_stats('cumtime')
stats.print_stats()

위 코드는 profile_output 파일의 결과를 가져온 후 profile_output_text를 새로 만들어 결과를 출력한다. 난 결과가 길어 파일에 저장했는데, 바로 출력하고 싶다면 pstats.Stats의 stream 옵션을 빼주면 된다.

sort_stats() 메소드는 제공된 값에 따라 다른 기준으로 결과를 정렬한다.
많이 사용할 것 같은 몇 가지만 가져왔다. 전체 내용은 여기에서 볼 수 있다. 열거형 인자는 파이썬 3.7부터 사용할 수 있다.

유효한 문자열 인자유효한 열거형 인자(Enum)의미
'calls'SortKey.CALLS호출 수
'cumulative', 'cumtime'SortKey.CUMULATIVE누적 시간
'filename'SortKey.FILENAME파일 이름
'time', 'tottime'SortKey.TIME내부 시간
'name'SortKey.NAME함수 이름

참고

profile
developer hamdoe

0개의 댓글