timeit
— 작은 코드 조각의 실행 시간 측정¶
소스 코드: Lib/timeit.py
이 모듈은 파이썬 코드의 작은 조각의 시간을 측정하는 간단한 방법을 제공합니다. 명령 줄 인터페이스뿐만 아니라 콜러블도 있습니다. 실행 시간을 측정에 따르는 흔한 함정들을 피할 수 있습니다. O’Reilly가 출판한 Python Cookbook에 있는 Tim Peters의 “Algorithms” 장의 개요도 참조하십시오.
기본 예제¶
다음 예제에서는 명령 줄 인터페이스를 사용하여 세 가지 다른 표현식을 비교하는 방법을 보여줍니다:
$ python3 -m timeit '"-".join(str(n) for n in range(100))'
10000 loops, best of 5: 30.2 usec per loop
$ python3 -m timeit '"-".join([str(n) for n in range(100)])'
10000 loops, best of 5: 27.5 usec per loop
$ python3 -m timeit '"-".join(map(str, range(100)))'
10000 loops, best of 5: 23.2 usec per loop
이것은 파이썬 인터페이스로는 다음과 같이 할 수 있습니다:
>>> import timeit
>>> timeit.timeit('"-".join(str(n) for n in range(100))', number=10000)
0.3018611848820001
>>> timeit.timeit('"-".join([str(n) for n in range(100)])', number=10000)
0.2727368790656328
>>> timeit.timeit('"-".join(map(str, range(100)))', number=10000)
0.23702679807320237
콜러블을 파이썬 인터페이스로 전달할 수도 있습니다:
>>> timeit.timeit(lambda: "-".join(map(str, range(100))), number=10000)
0.19665591977536678
그러나 timeit()
은 명령 줄 인터페이스가 사용될 때만 반복 횟수를 자동으로 결정합니다. 예제 절에서 고급 예제를 찾을 수 있습니다.
파이썬 인터페이스¶
이 모듈은 세 개의 편리 함수와 하나의 공용 클래스를 정의합니다:
-
timeit.
timeit
(stmt='pass', setup='pass', timer=<default timer>, number=1000000, globals=None)¶ 지정된 문장, setup 코드 및 timer 함수로
Timer
인스턴스를 만들고, number 실행으로timeit()
메서드를 실행합니다. 선택적 globals 인자는 코드를 실행할 이름 공간을 지정합니다.버전 3.5에서 변경: 선택적 globals 매개 변수가 추가되었습니다.
-
timeit.
repeat
(stmt='pass', setup='pass', timer=<default timer>, repeat=5, number=1000000, globals=None)¶ 주어진 문장, setup 코드 및 timer 함수로
Timer
인스턴스를 생성하고, 주어진 repeat 카운트와 number 실행으로repeat()
메서드를 실행합니다. 선택적 globals 인자는 코드를 실행할 이름 공간을 지정합니다.버전 3.5에서 변경: 선택적 globals 매개 변수가 추가되었습니다.
버전 3.7에서 변경: repeat의 기본값이 3에서 5로 변경되었습니다.
-
timeit.
default_timer
()¶ 기본 타이머, 항상
time.perf_counter()
입니다.버전 3.3에서 변경: 이제
time.perf_counter()
가 기본 타이머입니다.
-
class
timeit.
Timer
(stmt='pass', setup='pass', timer=<timer function>, globals=None)¶ 작은 코드 조각의 실행 속도를 측정하기 위한 클래스.
생성자는 시간 측정될 문장, 설정에 사용되는 추가 문장 및 타이머 함수를 받아들입니다. 두 문장의 기본값은
'pass'
입니다; 타이머 함수는 플랫폼에 따라 다릅니다 (모듈 독스트링을 참조하십시오). stmt와 setup은 여러 줄에 걸친 문자열 리터럴을 포함하지 않는 한;
나 줄 바꿈으로 구분된 여러 개의 문장을 포함 할 수도 있습니다. 문장은 기본적으로 timeit의 이름 공간 내에서 실행됩니다; 이 동작은 globals에 이름 공간을 전달하여 제어 할 수 있습니다.첫 번째 문장의 실행 시간을 측정하려면,
timeit()
메서드를 사용하십시오.repeat()
와autorange()
메서드는timeit()
을 여러 번 호출하는 편리 메서드입니다.setup의 실행 시간은 전체 측정 실행 시간에서 제외됩니다.
stmt와 setup 매개 변수는 인자 없이 호출 할 수 있는 객체를 받아들일 수도 있습니다. 이렇게 하면
timeit()
에 의해 실행될 타이머 함수에 그들에 대한 호출을 포함시킵니다. 이때는 여분의 함수 호출로 인해 타이밍 오버헤드가 약간 더 커집니다.버전 3.5에서 변경: 선택적 globals 매개 변수가 추가되었습니다.
-
timeit
(number=1000000)¶ 주 문장의 number 실행의 시간을 측정합니다. setup 문장을 한 번 실행한 다음, 주 문장을 여러 번 실행하는 데 걸리는 시간을 초 단위로 float로 반환합니다. 인자는 루프를 통과하는 횟수이며, 기본값은 백만입니다. 주 문장, setup 문장 및 사용할 타이머 함수는 생성자에 전달됩니다.
-
autorange
(callback=None)¶ timeit()
를 호출하는 횟수를 자동으로 결정합니다.이 함수는 총 시간이 0.2초 이상이 될 때까지
timeit()
을 반복적으로 호출하고, 최종 (루프 수, 해당 루프 수에 소요된 시간)을 반환하는 편리 함수입니다. 실행 시간이 적어도 0.2초가 될 때까지 1, 2, 5, 10, 20, 50 … 로 루프 수를 증가시키면서timeit()
을 호출합니다.callback이 주어지고
None
이 아니면, 각 시도 다음에 두 개의 인자로 호출합니다:callback(number, time_taken)
.버전 3.6에 추가.
-
repeat
(repeat=5, number=1000000)¶ timeit()
을 몇 번 호출합니다.이것은 반복적으로
timeit()
을 호출하여 결과 리스트를 반환하는 편리 함수입니다. 첫 번째 인자는timeit()
을 호출할 횟수를 지정합니다. 두 번째 인자는timeit()
에 대한 number 인자를 지정합니다.참고
결과 벡터로부터 평균과 표준 편차를 계산하고 이를 보고하고 싶을 수 있습니다. 하지만, 이것은 별로 유용하지 않습니다. 일반적으로, 가장 낮은 값이 여러분의 기계가 주어진 코드 조각을 얼마나 빨리 실행할 수 있는지에 대한 하한값을 제공합니다; 결과 벡터의 더 높은 값은 일반적으로 파이썬의 속도 변동성 때문이 아니라, 시간 측정의 정확성을 방해하는 다른 프로세스에 의해 발생합니다. 따라서 결과의
min()
이 여러분이 관심을 기울여야 할 유일한 숫자일 것입니다. 그 후에, 전체 벡터를 살펴보고 통계보다는 상식을 적용해야 합니다.버전 3.7에서 변경: repeat의 기본값이 3에서 5로 변경되었습니다.
-
print_exc
(file=None)¶ 측정되는 코드로부터의 트레이스백을 인쇄하는 도우미.
일반적인 사용:
t = Timer(...) # outside the try/except try: t.timeit(...) # or t.repeat(...) except Exception: t.print_exc()
표준 트레이스백에 비해 장점은 컴파일된 템플릿의 소스 행이 표시된다는 것입니다. 선택적 file 인자는 트레이스백을 보내야 할 곳을 지시합니다; 기본값은
sys.stderr
입니다.
-
명령 줄 인터페이스¶
명령 줄에서 프로그램으로 호출할 때, 다음 형식이 사용됩니다:
python -m timeit [-n N] [-r N] [-u U] [-s S] [-h] [statement ...]
이때 다음 옵션을 지원합니다:
-
-n
N
,
--number
=N
¶ ‘statement’를 실행하는 횟수
-
-r
N
,
--repeat
=N
¶ 타이머 반복 횟수 (기본값 5)
-
-s
S
,
--setup
=S
¶ 초기에 한 번 실행될 문장 (기본값
pass
)
-
-p
,
--process
¶
벽시계 시간이 아니라 프로세스 시간을 측정합니다, 기본값인
time.perf_counter()
대신time.process_time()
을 사용합니다버전 3.3에 추가.
-
-u
,
--unit
=U
¶ 타이머 출력의 시간 단위를 지정합니다; nsec, usec, msec 또는 sec 중에서 선택할 수 있습니다.
버전 3.5에 추가.
-
-v
,
--verbose
¶
날 시간 측정 결과를 인쇄합니다; 더 많은 자릿수 정밀도를 위해서는 반복하십시오
-
-h
,
--help
¶
짧은 사용법 메시지를 출력하고 종료합니다
여러 줄의 문장은 각 줄을 별도의 statement 인자로 지정하여 제공할 수 있습니다; 들여쓰기 된 줄은 인자를 따옴표로 묶고 선행 공백을 사용하면 됩니다. 여러 개의 -s
옵션도 비슷하게 취급됩니다.
-n
이 주어지지 않으면, 총 시간이 최소 0.2초가 될 때까지 시퀀스 1, 2, 5, 10, 20, 50, … 에서 증가하는 숫자를 시도하여 적절한 루프 수가 계산됩니다.
default_timer()
측정은 같은 기계에서 실행되는 다른 프로그램의 영향을 받을 수 있으므로, 정확한 시간 측정이 필요할 때 가장 좋은 방법은 시간 측정을 몇 번 반복하고 가장 좋은 시간을 사용하는 것입니다. 이 작업에는 -r
옵션이 좋습니다; 대부분의 경우 기본값인 5번 반복으로 충분할 것입니다. time.process_time()
을 사용하여 CPU 시간을 측정 할 수 있습니다.
참고
pass 문을 실행하는 것과 관련된 어떤 기준 오버헤드가 있습니다. 여기에 있는 코드는 그것을 숨기려고 시도하지는 않지만, 여러분은 신경 써야 합니다. 기준 오버헤드는 인자 없이 프로그램을 호출하여 측정 할 수 있으며, 파이썬 버전마다 다를 수 있습니다.
예제¶
처음에 한 번만 실행되는 setup 문을 제공 할 수 있습니다:
$ python -m timeit -s 'text = "sample string"; char = "g"' 'char in text'
5000000 loops, best of 5: 0.0877 usec per loop
$ python -m timeit -s 'text = "sample string"; char = "g"' 'text.find(char)'
1000000 loops, best of 5: 0.342 usec per loop
>>> import timeit
>>> timeit.timeit('char in text', setup='text = "sample string"; char = "g"')
0.41440500499993504
>>> timeit.timeit('text.find(char)', setup='text = "sample string"; char = "g"')
1.7246671520006203
Timer
클래스와 그 메서드를 사용하여 같은 작업을 수행 할 수 있습니다:
>>> import timeit
>>> t = timeit.Timer('char in text', setup='text = "sample string"; char = "g"')
>>> t.timeit()
0.3955516149999312
>>> t.repeat()
[0.40183617287970225, 0.37027556854118704, 0.38344867356679524, 0.3712595970846668, 0.37866875250654886]
다음 예제는 여러 줄을 포함하는 표현식의 시간을 측정하는 방법을 보여줍니다. 여기서 우리는 누락되었거나 존재하는 객체 어트리뷰트를 검사하는데 hasattr()
과 try
/except
를 사용하는 비용을 비교합니다:
$ python -m timeit 'try:' ' str.__bool__' 'except AttributeError:' ' pass'
20000 loops, best of 5: 15.7 usec per loop
$ python -m timeit 'if hasattr(str, "__bool__"): pass'
50000 loops, best of 5: 4.26 usec per loop
$ python -m timeit 'try:' ' int.__bool__' 'except AttributeError:' ' pass'
200000 loops, best of 5: 1.43 usec per loop
$ python -m timeit 'if hasattr(int, "__bool__"): pass'
100000 loops, best of 5: 2.23 usec per loop
>>> import timeit
>>> # attribute is missing
>>> s = """\
... try:
... str.__bool__
... except AttributeError:
... pass
... """
>>> timeit.timeit(stmt=s, number=100000)
0.9138244460009446
>>> s = "if hasattr(str, '__bool__'): pass"
>>> timeit.timeit(stmt=s, number=100000)
0.5829014980008651
>>>
>>> # attribute is present
>>> s = """\
... try:
... int.__bool__
... except AttributeError:
... pass
... """
>>> timeit.timeit(stmt=s, number=100000)
0.04215312199994514
>>> s = "if hasattr(int, '__bool__'): pass"
>>> timeit.timeit(stmt=s, number=100000)
0.08588060699912603
timeit
모듈이 여러분이 정의한 함수에 액세스하도록 하려면, import 문이 포함된 setup 매개 변수를 전달하면 됩니다:
def test():
"""Stupid test function"""
L = [i for i in range(100)]
if __name__ == '__main__':
import timeit
print(timeit.timeit("test()", setup="from __main__ import test"))
또 다른 옵션은 globals()
를 globals 매개 변수로 전달해서, 여러분의 현재 전역 이름 공간에서 코드가 실행되도록 하는 것입니다. 임포트를 개별적으로 지정하는 것보다 편리 할 수 있습니다:
def f(x):
return x**2
def g(x):
return x**4
def h(x):
return x**8
import timeit
print(timeit.timeit('[func(42) for func in (f,g,h)]', globals=globals()))