파이썬에서는 코드 실행 시간을 측정하는 다양한 방법이 있습니다. 그중 하나는 내장 time 모듈을 사용해 프로그램 실행 전후의 시간을 기록하는 방식입니다. 하지만 더 정밀한 성능 측정이 필요하다면 어떻게 해야 할까요?
파이썬 timeit이란?
프로그램이 실행되는 동안 백그라운드에서도 수많은 프로세스가 함께 동작합니다. 일반적인 time 모듈은 이러한 백그라운드 프로세스의 실행 시간까지는 고려하지 못합니다. 따라서 정확한 시간 성능 측정이 필요하다면 timeit 모듈을 사용하는 것이 가장 좋습니다.
timeit 모듈은 코드를 약 100만 회(기본값) 실행하고, 그중 가장 짧게 걸린 최소 실행 시간을 기준으로 결과를 산출합니다. 이를 통해 운영체제 스케줄링 등 외부 요인에 의한 오차를 최소화할 수 있습니다.
timeit으로 파이썬 실행 시간 구하기
timeit 모듈은 여러 가지 방식으로 사용할 수 있습니다. 가장 간단한 방법 중 하나는 파이썬 CLI(명령줄 인터페이스)에서 직접 사용하는 것입니다.
예제 1 – CLI에서 timeit 사용하기
먼저 명령줄에서 timeit 모듈을 사용해 보겠습니다. CLI를 사용하면 모듈이 동일한 코드에 대해 반복 횟수를 자동으로 결정한다는 점을 확인할 수 있습니다.
C:\Users\rajesh>python -m timeit "'-'.join(str(n) for n in range(200))" 1000 loops, best of 3: 290 usec per loop C:\Users\rajesh>python -m timeit "'-'.join(str(n) for n in range(200))" 1000 loops, best of 3: 292 usec per loop C:\Users\rajesh>python -m timeit "'-'.join(str(n) for n in range(200))" 1000 loops, best of 3: 294 usec per loop
같은 코드를 세 번 실행했지만 매번 미세하게 다른 결과가 나오는 것을 볼 수 있습니다. 이는 시스템 상태에 따른 자연스러운 변동입니다.
예제 2 – 스크립트에서 timeit 사용하기
다음은 좀 더 간단한 예제입니다. 단, 위와 같은 명령줄 문법을 사용하지 않는 경우에는 먼저 import timeit 문으로 모듈을 가져와야 합니다.
# timeit 모듈 임포트
import timeit
# 측정 대상 코드
print('x' * 5)
print('x' + 'x' + 'x' + 'x' + 'x')
# 문자열 형태의 코드를 timeit에 전달하고 소요 시간 출력
# ... number 인자로 반복 횟수 지정 가능
print(timeit.timeit("y = 'x' * 3", number=10000000))
print(timeit.timeit("xy = 'x' + 'x' + 'x' + 'x' + 'x'", number=10000000))
위 코드에서는 따옴표로 묶인 문자열 형태의 문장을 timeit.timeit() 메서드에 전달하고, number 인자를 지정해 반복 횟수를 늘렸습니다.
출력 결과
프로그램 첫 번째 실행 결과:
xxxxx xxxxx 0.9041136896626635 0.7712796073957123
두 번째 실행 결과:
xxxxx xxxxx 0.7317015874427751 0.7312688195585995
세 번째 실행 결과:
xxxxx xxxxx 0.7240862411172824 0.7255863890794246
프로그램을 여러 번(세 번) 실행해 보니 실행 시간이 점차 줄어드는 것을 확인할 수 있습니다. 매번 수작업으로 반복하는 대신, 프로그램 차원에서 반복을 처리할 수도 있습니다.
# timeit 모듈 임포트
import timeit
# 문장에 대해 timeit을 호출하고 반환된 시간 출력
# ... number 인자로 반복 횟수, repeat 인자로 반복 세트 수 지정
print(timeit.repeat("y = 'x' * 3", number=10000000, repeat=5))
print()
print(timeit.repeat("xy= 'x' + 'x' + 'x' + 'x' + 'x'", number=10000000, repeat=5))
출력 결과
[0.7303736343436382, 0.7213687552991258, 0.7362311105941466, 0.7293136666273243, 0.7278277732068212] [0.7388334197158559, 0.7378481457977326, 0.9486733868277772, 0.735295442480929, 0.7398226849056382]
timeit.repeat() 함수는 지정한 횟수만큼 전체 측정 과정을 반복하고, 각 반복의 결과를 리스트로 반환합니다. 이렇게 하면 한 번의 측정에서 발생할 수 있는 우연한 오차를 걸러내고 신뢰도 높은 결과를 얻을 수 있습니다.
timeit으로 여러 문장 실행하기
timeit 모듈에서는 여러 문장을 함께 측정할 수도 있습니다. 각 문장은 세미콜론(;)으로 구분합니다. 물론 실제 코딩에서 권장되는 방식은 아니지만, 긴 코드 조각을 간단히 지정할 때 유용합니다.
# timeit 모듈 임포트
import timeit
# 세미콜론으로 여러 문장 구분
print(timeit.repeat("x = 2; x *= 2", number=100000000))
print(timeit.repeat("x = 1; x *= 4", number=100000000))
출력 결과
[24.859605879029118, 23.58795536845994, 23.95826726353284] [22.70639977603264, 21.380195994245724, 20.71523588130414]
setup 인자로 사용자 정의 함수 벤치마크하기
timeit에서 직접 만든 함수를 측정하려면 setup 인자를 사용합니다. 이 인자에는 호출할 함수를 임포트하는 import 문을 지정합니다.
# timeit 모듈 임포트
import timeit
def func1():
return 1
def func2():
return sum([-1, 0, 1, 1])
# 함수 테스트
print(func1())
print(func2())
# setup 인자를 전달해 함수 호출
print(timeit.repeat("func1()", setup="from __main__ import func1"))
print(timeit.repeat("func2()", setup="from __main__ import func2"))
위 프로그램에서는 func1() 메서드와 func2() 메서드의 성능을 서로 비교해 벤치마크했습니다.
출력 결과
1 1 [0.44798489246658874, 0.4411512652046069, 0.44570416580426686] [1.583622557983199, 1.5712399227517881, 1.5469479030713984]
func1()이 하는 작업이 훨씬 적기 때문에 실행 속도도 훨씬 빠릅니다. 이처럼 timeit을 활용하면 유사한 기능을 수행하는 코드들의 성능을 객관적으로 비교할 수 있습니다.
정리
지금까지 timeit 모듈을 활용해 작은 파이썬 코드 조각의 성능을 측정하는 방법을 살펴봤습니다. CLI와 스크립트 두 가지 방식을 모두 지원하며, number, repeat, setup 같은 옵션을 적절히 조합하면 신뢰할 수 있는 벤치마크 결과를 얻을 수 있습니다. 코드 최적화나 알고리즘 비교가 필요할 때 timeit을 적극적으로 활용해 보시기 바랍니다.