Модуль timeit
предоставляет простой способ измерения времени выполнения (производительности) маленьких кусочков кода Python.
Он имеет как интерфейс командной строки, так и программный интерфейс. Это позволяет избежать ряда распространенных ловушек для измерения времени выполнения.
timeit
:Использование интерфейса командной строки для сравнения производительности трех различных выражений.
$ 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
То же самое, только достигнуто с помощью интерфейса Python:
>>> 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
Вызываемые объекты (функции, экземпляры классов и т.д.) также могут быть переданы из интерфейса Python.
>>> timeit.timeit(lambda: "-".join(map(str, range(100))), number=10000) 0.19665591977536678
Обратите внимание, что функция timeit.timeit()
автоматически определяет количество повторений только при использовании интерфейса командной строки.
Можно предоставить оператор настройки -s
, который выполняется только один раз в начале.
Командная строка:
$ 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
То же самое можно сделать с помощью класса timeit.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
доступ к определенным функциям в коде, можно передать параметр настройки, который содержит оператор импорта:
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()))