Python таймер выполнения кода

timeit — Измерение времени выполнения небольших фрагментов кода¶

Модуль предоставляет простой способ замера времени выполнения небольших фрагментов Python кода. Реализует как интерфейс командной строки , так и вызываемый интерфейс . Позволяет избежать ряда распространенных ловушек для измерения времени выполнения. См. также введение Тима Петерса в главе «Алгоритмы» Сборника рецептов Python, опубликованного в O’Reilly.

Основные примеры¶

В следующем примере показано, как можно использовать интерфейс командной строки для сравнения трёх различных выражений:

$ 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() автоматически определяет количество повторений только при использовании интерфейса командной строки. В разделе Примеры приведены дополнительные примеры.

Python Интерфейс¶

Модуль определяет три удобные функции и публичный класс:

timeit. timeit ( stmt=’pass’, setup=’pass’, timer= , number=1000000, globals=None ) ¶

Создать Timer сущность с переданным оператором, setup кодом и timer функцией с последующим запуском её методом timeit() с number выполнений. Необязательный аргумент globals указывает пространство имён для выполнения кода.

Изменено в версии 3.5: Добавлен необязательный параметр globals.

Создать Timer сущность с переданным оператором, setup кодом и timer функцией с последующим запуском её методом repeat() с заданным repeat счётчиком и number выполнений. Необязательный аргумент globals указывает пространство имён для выполнения кода.

Изменено в версии 3.5: Добавлен необязательный параметр globals.

Изменено в версии 3.7: По умолчанию значение repeat изменено с 3 на 5.

Таймер по умолчанию, который всегда time.perf_counter() .

Изменено в версии 3.3: time.perf_counter() теперь является таймером по умолчанию.

Класс для замеров скорости выполнения небольших фрагментов кода.

Конструктор принимает оператор для синхронизации, дополнительный оператор используемый для настройки и функцию таймера. Оба оператора по умолчанию — ‘pass’ ; функция таймера зависит от платформы (см. doc string модуля). stmt и setup могут также содержать несколько операторов, разделенных ; или новыми строками, если они не содержат многострочных строковых литералов. По умолчанию оператор будет выполняться в пространстве имён timeit; этим поведением можно управлять путём передачи пространства имён в globals.

Для измерения времени выполнения первого оператора используйте метод timeit() . Методы repeat() и autorange() являются удобными способами многократного вызова timeit() .

Время выполнения setup исключается из общего времени выполнения.

Параметры stmt и setup могут также принимать объекты, вызываемые без аргументов. Вызовы будут встроены в функцию таймера, которая затем будет выполняться timeit() . Следует отметить, что служебные данные синхронизации в этом случае немного больше из-за дополнительных вызовов функций.

Изменено в версии 3.5: Добавлен необязательный параметр globals.

Время number выполнений основного оператора. При этом оператор установки выполняется один раз, а затем возвращает время, необходимое для выполнения основного оператора, несколько раз, измеренное в секундах как float. Аргумент — это число раз в цикле, по умолчанию равное одному миллиону. Главный оператор, оператор установки и используемая функция таймера передаются конструктору.

По умолчанию timeit() временно отключает сборщик мусора во время синхронизации. Преимущество этого подхода в том, что он делает независимые тайминги более сопоставимыми. Недостатком является то, что GC может быть важным компонентом эффективности измеряемой функции. Если это так, GC может быть повторно включен в качестве первого оператора в setup строке. Например:

timeit.Timer('for i in range(10): oct(i)', 'gc.enable()').timeit() 

Автоматически определяет количество вызовов timeit() .

Это удобная функция, которая вызывает timeit() повторно, так что общее время >= 0.2 секунды, возвращая возможное (количество циклов, время, занятое для этого числа циклов). Она вызывает timeit() с возрастающими числами из последовательности 1, 2, 5, 10, 20, 50, … пока время не составит не менее 0.2 секунды.

Если callback передано и не None , то будет вызываться после каждого пробного с двумя аргументами: callback(number, time_taken) .

Это удобная функция, которая вызывает timeit() повторно, возвращая список результатов. Первый аргумент указывает количество вызовов timeit() . Второй аргумент указывает number аргумент для timeit() .

Соблазнительно вычислить среднее и стандартное отклонение от вектора результата и сообщить об этом. Однако это не очень полезно. В типовом случае самое низкое значение даёт нижнюю границу для того, как быстро машина может запустить данный фрагмент код; более высокие значения вектора результата обычно вызваны не изменчивостью скорости Python’а, а другими процессами, мешающими точности синхронизации. Так что min() результата, наверное, единственное число, которое вас должно заинтересовать. После этого следует посмотреть на весь вектор и применить здравый смысл, а не статистику.

Изменено в версии 3.7: Значение repeat по умолчанию изменено с 3 на 5.

Помощник для печати трейсбэка из замеряемого кода.

t = Timer(. ) # вне try/except try: t.timeit(. ) # или t.repeat(. ) except Exception: t.print_exc() 

Преимущество по сравнению со стандартным трейсбэком заключается в том, что в скомпилированном шаблоне отображаются исходные строки. Необязательный аргумент file указывает место отправки трейсбэк; значение по умолчанию — sys.stderr .

Интерфейс командной строки¶

При вызове программы из командной строки используется следующая форма:

python -m timeit [-n N] [-r N] [-u U] [-s S] [-h] [statement . ] 

Далее приводится объяснение назначений опций:

сколько раз выполнить „statement“

сколько раз повторять таймер (по умолчанию 5)

оператор для выполнения один раз изначально (по умолчанию pass )

измерить время процесса, а не время обхода, используя time.process_time() вместо time.perf_counter() , что является значением по умолчанию

определяют единицу времени для вывода таймера; можно выбрать nsec, usec, msec или sec

печать необработанных результатов замеров; повтор для большей точности цифр

распечатать короткое сообщение об использовании и выйти из программы

Многострочный оператор может быть задан путём указания каждой строки в качестве отдельного аргумента оператора; строки с отступами можно заключить в кавычки и использовать начальные пробелы. Несколько опций -s обрабатываются одинаково.

Если -n не дано, подходящее количество циклов вычисляется путём попытки увеличения чисел из последовательности 1, 2, 5, 10, 20, 50,… пока общее время не составит по меньшей мере 0.2 секунды.

default_timer() измерения могут быть затронуты другими программами, работающими на той же машине, поэтому лучше всего, когда необходимо точное время, повторить время несколько раз и использовать лучшее время. Опция -r хороша для этого; по умолчанию 5 повторов, вероятно, достаточно в большинстве случаев. Для измерения времени ЦПУ можно использовать time.process_time() .

Есть определенные базовые накладные расходы, связанные с выполнением оператора pass. Здесь код не пытается скрыть, но вы должны знать об этом. Базовые издержки могут быть измерены путём вызова программы без аргументов, и они могут отличаться между Python версиями.

Примеры¶

Можно предоставить оператор настройки, который выполняется только один раз в начале:

$ 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 модулю доступ к определенным функциям, можно передать параметр setup, содержащий оператор import:

def test(): """Глупая тестовая функция""" 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())) 

Источник

Читайте также:  Php request application json
Оцените статью