Python에서 시간측정하기
요즈음 파이썬의 내부 구조를 자세히 이해해야할 필요성을 느껴서 시간 측정을 자주 하고 있는데, 그 방법에 대해서 몇가지 정리해보았다. (고성능 파이썬이라는 책을 참고하면서 작성했다)
자주 사용해야 할 때 (decorator)
자주 사용을 해야할 때는 아무래도 최대한 간단하게 쓸 수 있도록 미리 작성해두는 편이 편하다. 그래서 위의 책에서는 decorator를 이용하기를 추천하는데, 좋은 방법이라고 생각한다.
import time
from functools import wraps
def check_time(function):
@wraps(function)
def measure(*args, **kwargs):
start_time = time.time()
result = function(*args, **kwargs)
end_time = time.time()
print(f"@check_time: {function.__name__} took {end_time - start_time}")
return result
return measure
위의 코드는 check_time
이라는 decorator이고, 함수를 실행하기 전후로 시간을 측정한 뒤 그 차이값을 출력해주는 역할을 한다. 이는 아래처럼 사용이 가능하다.
@check_time
def test_function():
for _ in range(10000):
print("Just print something")
if __name__ == "__main__":
test_function()
출력값은 아래처럼 나타난다.
$ python3.6 test.py
Just print something
Just print something
Just print something
Just print something
Just print something
...
@check_time: test_function took 0.03430891036987305
timeit 모듈
timeit 모듈은 짧은 코드의 실행시간을 확인해볼 수 있는 모듈이다. CLI로 실행하는 모듈이며, 아래와 같은 방법으로 간단하게 사용이 가능하다. (Python에서는 특정 모듈을 커맨드라인에서 실행할 때 -m
옵션으로 실행이 가능하다.)
$ python3.6 -m timeit '[x**2 for x in range(10000)]'
100 loops, best of 3: 2.38 msec per loop
$ python3.6 -m timeit 'list(map(lambda x: x**2, range(10000)))'
100 loops, best of 3: 3.11 msec per loop
위의 코드는 0~9999까지의 숫자들의 제곱이 담긴 리스트를 만드는 코드이다. 하나는 list comprehension
으로, 하나는 map
과 list
를 이용하여 생성해내었다. (map의 결과물은 list
나, dict
가 아닌 iterator
이다..! 1)
timeit 모듈은 물론 프로그램 코드에서도 사용이 가능하다. 하지만, 아래처럼 일시적으로 GC를 비활성화시킨다고 하므로, 실제 코드와 실행시간이 차이날 수 있음을 알 수 있다. 하지만, 아래처럼 다시 gc를 활성화 시킬수도 있다.
Note: By default,
timeit()
temporarily turns offgarbage collection
during the timing. The advantage of this approach is that it makes independent timings more comparable. This disadvantage is that GC may be an important component of the performance of the function being measured. If so, GC can be re-enabled as the first statement in the setup string. For example:timeit.Timer('for i in range(10): oct(i)', 'gc.enable()').timeit()
time
명령어
이 방법은 제일 자주 쓰는 방법인데, 커맨드 라인에서 단순히 time
명령어를 앞에 붙이는 방식이다. 아래와 같은 방식으로 사용하며, real
, user
, sys
등 세가지의 정보를 얻을 수 있다. 대략적인 의미는 real
이 경과한 총 시간, user
는 커널이 아닌 코드가 소비한 시간, sys
는 커널 함수 때문에 소비한 시간이다. macOS를 기준으로, -l
항목을 같이 넘겨준다면, 메모리와 관련된 자세한 결과를 받을 수 있다. (다른 OS는 --verbose
를 시도해보자. 둘이 같은 기능은 아니다..)
$ time python test.py
{프로그램 출력값}
real 0m0.100s
user 0m0.032s
sys 0m0.043s
그 외에도 cProfile
이라는 모듈을 이용해서 측정하는 방법이 있는데, 그 방법은 나중에 다시 정리하기로…
-
https://docs.python.org/3/library/functions.html#map Return an iterator that applies function to every item of iterable, yielding the results. … ↩