Timeit.timeit: примеры (PYTHON)
timeit.timeit(stmt: str, setup: str, number: int): floatОписание функции timeit.timeit
Функция timeit.timeit() из стандартного модуля timeit применяется для измерения времени выполнения небольших фрагментов кода. Её основное назначение - сравнительный анализ производительности различных подходов или микрооптимизаций. Результат возвращается в виде числа с плавающей точкой, обозначающего общее время в секундах для заданного количества выполнений измеряемого кода.
Аргументы функции
- stmt (по умолчанию
'pass'): Строка с кодом, время выполнения которого необходимо измерить. Может содержать несколько инструкций, разделённых точкой с запятой. - setup (по умолчанию
'pass'): Строка с кодом, который выполняется один раз перед началом измерений. Обычно здесь размещают импорты модулей или подготовку данных. - timer: Объект таймера. В большинстве случаев используется значение по умолчанию
time.perf_counter, которое обеспечивает высокую точность. - number (по умолчанию 1000000): Количество повторений выполнения кода из аргумента
stmt. Функция возвращает общее время для всех повторений. - globals (по умолчанию
None): Словарь с глобальными переменными, в контексте которых будет выполняться код. Позволяет использовать функции и переменные из текущей области видимости.
Возвращаемое значение
Функция возвращает значение типа float - общее время в секундах, затраченное на выполнение кода из stmt указанное количество раз (number).
Краткие примеры использования
Простой вызов
Измерение времени создания списка.
import timeit
result = timeit.timeit(stmt="[i for i in range(100)]")
print(result)5.234567890123456
Использование параметра setup
import timeit
code = '''
result = []
for i in range(100):
result.append(i)
'''
setup_code = "import random"
result = timeit.timeit(stmt=code, setup=setup_code, number=10000)
print(result)0.4567890123456789
Изменение количества выполнений (number)
import timeit
result = timeit.timeit(stmt="pow(2, 100)", number=500000)
print(result)0.7890123456789012
Работа с глобальными переменными через globals
import timeit
def my_func():
return sum(range(1000))
result = timeit.timeit(stmt="my_func()", globals=globals(), number=1000)
print(result)0.12345678901234567
Использование собственного таймера
import timeit, time
result = timeit.timeit(stmt="time.sleep(0.001)", setup="import time", timer=time.process_time, number=100)
print(result)0.0012345678901234567
Похожие функции в Python
timeit.repeat
Функция timeit.repeat() принимает те же аргументы, что и timeit(), но также параметр repeat. Она выполняет измерение несколько раз и возвращает список результатов. Полезна для оценки стабильности времени выполнения.
Модуль profile и cProfile
Модули profile и cProfile предназначены для профилирования всего кода, а не только небольших фрагментов. Они показывают время выполнения каждой функции, включая вложенные вызовы, что помогает найти узкие места в программе.
time.perf_counter и time.process_time
Функции time.perf_counter() и time.process_time() возвращают текущее время с высокой точностью. Их используют для ручного измерения интервалов, оборачивая участок кода в вызовы до и после. perf_counter учитывает время сна системы, а process_time - только процессорное время текущего процесса.
Аналоги функции в других языках программирования
PHP: microtime
$start = microtime(true);
for ($i = 0; $i < 1000000; $i++) { /* код */ }
$time = microtime(true) - $start;
echo $time;0.12345600128174
JavaScript: console.time и performance.now
console.time('test');
for (let i = 0; i < 1000000; i++) { /* код */ }
console.timeEnd('test');
// Или
const start = performance.now();
// код
const duration = performance.now() - start;test: 12.345 ms
Java: System.nanoTime
long start = System.nanoTime();
for (int i = 0; i < 1000000; i++) { /* код */ }
long duration = System.nanoTime() - start;
System.out.println(duration / 1_000_000_000.0);0.123456789
C#: Stopwatch
using System.Diagnostics;
var sw = Stopwatch.StartNew();
for (int i = 0; i < 1000000; i++) { /* код */ }
sw.Stop();
Console.WriteLine(sw.Elapsed.TotalSeconds);0.1234567
Go: time.Since
package main
import (
"fmt"
"time"
)
func main() {
start := time.Now()
for i := 0; i < 1000000; i++ { /* код */ }
elapsed := time.Since(start)
fmt.Println(elapsed.Seconds())
}0.123456789
Lua: os.clock
local start = os.clock()
for i=1,1000000 do -- код end
local time = os.clock() - start
print(time)0.123456
Kotlin: measureTimeMillis
import kotlin.system.measureTimeMillis
val time = measureTimeMillis {
for (i in 1..1000000) { /* код */ }
}
println(time / 1000.0)0.123
Типичные ошибки при использовании
Измерение кода с побочными эффектами
Повторное выполнение кода, который изменяет состояние, может привести к некорректным результатам или ошибкам.
import timeit
counter = 0
result = timeit.timeit(stmt="counter += 1", globals=globals(), number=10)
print(f"Время: {result}, Счётчик: {counter}")Время: 1.234567890123456e-06, Счётчик: 10
Неверное использование globals для импорта
Если в коде stmt используются модули, их нужно импортировать либо в setup, либо передать через globals.
import timeit
# Ошибка: NameError: name 'math' is not defined
result = timeit.timeit(stmt="math.sqrt(4)", number=1000)NameError: name 'math' is not defined
Слишком малое значение number
Малое количество повторений может давать нестабильные результаты из-за погрешности таймера.
import timeit
result = timeit.timeit(stmt="pass", number=1)
print(result)1.234567890123456e-07
Измерение очень медленного кода с большим number
Установка чрезмерно большого числа повторений для долгого кода может надолго заблокировать выполнение программы.
Изменения в последних версиях Python
В Python 3.5 был добавлен параметр globals, что упростило использование функции в контексте текущего модуля.
Начиная с Python 3.8, по умолчанию в качестве таймера используется time.perf_counter с наивысшей доступной точностью. В более ранних версиях на Windows использовался time.clock, который устарел.
Расширенные примеры использования
Сравнение производительности двух операций
import timeit
list_comp = timeit.timeit(stmt="[x for x in range(1000)]", number=10000)
list_func = timeit.timeit(stmt="list(range(1000))", number=10000)
print(f"Генератор списка: {list_comp}")
print(f"Функция list: {list_func}")Генератор списка: 0.4567890123456789 Функция list: 0.23456789012345678
Использование с пользовательскими функциями и аргументами
import timeit
def calculate_power(base, exp):
return base ** exp
result = timeit.timeit(stmt="calculate_power(2, 100)", globals=globals(), number=500000)
print(result)0.567890123456789
Многократный запуск с помощью repeat
import timeit
results = timeit.repeat(stmt="sum(range(1000))", number=10000, repeat=5)
print(f"Результаты: {results}")
print(f"Лучшее время: {min(results)}")Результаты: [0.123456, 0.123457, 0.123455, 0.123458, 0.123454] Лучшее время: 0.123454
Измерение времени с использованием lambda-функций
import timeit
result = timeit.timeit(stmt="(lambda x: x*x)(5)", number=1000000)
print(result)0.09876543210987654
Использование timeit для оценки скорости доступа к атрибутам
import timeit
class TestClass:
attr = 1
obj = TestClass()
direct = timeit.timeit(stmt="obj.attr", globals=globals(), number=1000000)
getattr_call = timeit.timeit(stmt="getattr(obj, 'attr')", globals=globals(), number=1000000)
print(f"Прямой доступ: {direct}")
print(f"getattr: {getattr_call}")Прямой доступ: 0.04567890123456789 getattr: 0.12345678901234567
Измерение в контексте Jupyter Notebook
В Jupyter доступна магическая команда %timeit.
%timeit [x for x in range(1000)]10000 loops, best of 5: 23.4 µs per loop