В моём детстве питона измеряли в попугаях...
В моём детстве питона измеряли в попугаях...

Есть числа, которые полезно знать программистам на Python. Насколько быстро добавляется элемент в список? Как насчет открытия файла? Это занимает меньше миллисекунды? Если ваш алгоритм зависит от производительности, какую структуру данных вы должны использовать? Сколько памяти занимает число с плавающей запятой, один символ или пустая строка? Насколько быстр FastAPI по сравнению с Django?

Это перевод недавней работы Python Numbers Every Programmer Should Know от Michael Kennedy с подробными пояснениями для начинающих питонистов, которых нет у автора.

Python Numbers Every Programmer Should Know

Michael Kennedy в статье от 31.12.2025 решил собрать и зафиксировать ключевые показатели производительности, ориентированные на Python-разработчиков. Ниже вы найдёте подробную таблицу таких значений, сгруппированных по категориям. Под таблицей приведены несколько графиков для более глубокого анализа наиболее значимых результатов.

Также @avshkolснабдил материал пояснениями для начинающих - они приведены в спойлерах и в колонке Описание для каждой таблице.

Благодарности: вдохновлено материалом «Latency Numbers Every Programmer Should Know» и аналогичными ресурсами.

Исходный код бенчмарков доступен на гитхабе:

Системная информация

Бенчмарки выполнялись на железе и софте, описанном в этой таблице. Ваша система может быть быстрее или медленнее, самое важное здесь — это относительные сравнения между параметрами.

Свойство / параметр

Значение

Python Version

CPython 3.14.2

Hardware

Mac Mini M4 Pro

Platform

macOS Tahoe (26.2)

Processor

ARM

CPU Cores

14 physical / 14 logical

RAM

24 GB

Timestamp

2025-12-30

TL;DR; Ключевые параметры Python

Это вариант упрощённой «пирамиды» возрастающих значений времени или объёма памяти для типичных операций в Python. Более подробная информация приведена ниже.

Числа задержек для операций в Python (пирамида)

Операция

Описание

Время, нс

Время, мкс/мс

Относитель-ная скорость

Attribute read (obj.x)

Чтение атрибута объекта

14

0.014 мкс

Dict key lookup

Поиск ключа в словаре

22

0.022 мкс

1.5× атрибут

Function call (empty)

Вызов пустой функции

22

0.022 мкс

List append

Добавление элемента в список

29

0.029 мкс

2× атрибут

f-string formatting

Форматирование f-строки

65

0.065 мкс

3× функция

Exception raised + caught

Выброс и перехват исключения

140

0.14 мкс

10× атрибут

orjson.dumps() complex object

Сериализация сложного объекта (orjson)

310

0.31 мкс

json.loads() simple object

Десериализация простого объекта (json)

714

0.71 мкс

2× orjson

sum() 1,000 integers

Суммирование 1000 целых чисел

1 900

1.9 мкс

3× json

SQLite SELECT by primary key

SELECT по первичному ключу (SQLite)

3 600

3.6 мкс

5× json

Iterate 1,000-item list

Итерация по списку из 1000 элементов

7 900

7.9 мкс

2× SQLite read

Open and close file

Открытие и закрытие файла

9 100

9.1 мкс

2× SQLite read

asyncio run_until_complete (empty)

Запуск пустой async-функции

28 000

28 мкс

3× открытие файла

Write 1KB file

Запись файла 1 КБ

35 000

35 мкс

4× открытие файла

MongoDB find_one() by _id

Поиск по _id в MongoDB

121 000

121 мкс

3× запись 1 КБ

SQLite INSERT (with commit)

INSERT с коммитом (SQLite)

192 000

192 мкс

5× запись 1 КБ

Write 1MB file

Запись файла 1 МБ

207 000

207 мкс

6× запись 1 КБ

import json

Импорт модуля json

2 900 000

2.9 мс

15× запись 1 МБ

import asyncio

Импорт модуля asyncio

17 700 000

17.7 мс

6× import json

import fastapi

Импорт фреймворка fastapi

104 000 000

104 мс

6× import asyncio

Параметры расходования памяти (пирамида)

Объект

Описание

Размер, байты

Размер, КБ / МБ

Относитель-ный размер

Float

Число с плавающей точкой

24

0.024 КБ

Small int (cached 0–256)

Малое целое (кэшированное, 0–256)

28

0.028 КБ

Empty string

Пустая строка

41

0.041 КБ

Empty list

Пустой список

56

0.056 КБ

2× int

Empty dict

Пустой словарь

64

0.064 КБ

2× int

Empty set

Пустое множество

216

0.216 КБ

8× int

slots class (5 attrs)

Класс с slots (5 атрибутов)

212

0.212 КБ

8× int

Regular class (5 attrs)

Обычный класс (5 атрибутов)

694

0.694 КБ

25× int

List of 1,000 ints

Список из 1 000 целых чисел

36 056

36 КБ

Dict of 1,000 items

Словарь из 1 000 элементов

64 952

65 КБ

List of 1,000 slots instances

Список из 1 000 экземпляров с slots

81 000

81 КБ

List of 1,000 regular instances

Список из 1 000 обычных экземпляров

169 000

169 КБ

2× списка со slots

Empty Python process

Пустой процесс Python

16 000 000

16 МБ

Параметры Python, которые нужно знать (подробная версия)

Ниже приведена расширенная таблица, содержащая гораздо больше деталей.

Параметры для памяти:

Операция

Описание

Память

Empty Python process

Пустой процесс Python

15.73 MB

Empty string

Пустая строка

41 bytes

100-char string

Строка из 100 символов

141 bytes

Small int (0-256)

Малое целое (0–256)

28 bytes

Large int

Большое целое число

28 bytes

Float

Число с плавающей точкой

24 bytes

Empty list

Пустой список

56 bytes

List with 1,000 ints

Список из 1 000 целых чисел

35.2 KB

List with 1,000 floats

Список из 1 000 чисел с плавающей точкой

32.1 KB

Empty dict

Пустой словарь

64 bytes

Dict with 1,000 items

Словарь из 1 000 элементов

63.4 KB

Empty set

Пустое множество

216 bytes

Set with 1,000 items

Множество из 1 000 элементов

59.6 KB

Regular class instance (5 attrs)

Экземпляр обычного класса (5 атрибутов)

694 bytes

slots class instance (5 attrs)

Экземпляр класса с slots (5 атрибутов)

212 bytes

List of 1,000 regular class instances

Список из 1 000 экземпляров обычного класса

165.2 KB

List of 1,000 slots class instances

Список из 1 000 экземпляров класса с slots

79.1 KB

dataclass instance

Экземпляр dataclass

694 bytes

namedtuple instance

Экземпляр namedtuple

228 bytes

Основные операции:

Операция

Описание

Время

Add two integers

Сложение двух целых чисел

19.0 ns (52.7 млн операций/сек)

Add two floats

Сложение двух чисел с плавающей точкой

18.4 ns (54.4 млн операций/сек)

String concatenation (small)

Конкатенация строк (небольших)

39.1 ns (25.6 млн операций/сек)

f-string formatting

Форматирование f-строки

64.9 ns (15.4 млн операций/сек)

.format()

Форматирование через .format()

103 ns (9.7 млн операций/сек)

% formatting

Форматирование через %

89.8 ns (11.1 млн операций/сек)

List append

Добавление элемента в список

28.7 ns (34.8 млн операций/сек)

List comprehension (1,000 items)

Генератор списков (1 000 элементов)

9.45 мкс (105.8 тыс. операций/сек)

Equivalent for-loop (1,000 items)

Эквивалентный цикл for (1 000 элементов)

11.9 мкс (83.9 тыс. операций/сек)

Коллекции:

Операция

Описание

Время

Dict lookup by key

Поиск по ключу в словаре

21.9 ns (45.7 млн операций/сек)

Set membership check

Проверка принадлежности элемента множеству

19.0 ns (52.7 млн операций/сек)

List index access

Доступ к элементу списка по индексу

17.6 ns (56.8 млн операций/сек)

List membership check (1,000 items)

Проверка принадлежности в списке (1000 эл.)

3.85 мкс (259.6 тыс. операций/сек)

len() on list

Вызов len() для списка

18.8 ns (53.3 млн операций/сек)

Iterate 1,000-item list

Итерация по списку из 1 000 элементов

7.87 мкс (127.0 тыс. операций/сек)

Iterate 1,000-item dict

Итерация по словарю из 1 000 элементов

8.74 мкс (114.5 тыс. операций/сек)

sum() of 1,000 ints

Суммирование 1 000 целых чисел

1.87 мкс (534.8 тыс. операций/сек)

Атрибуты:

Операция

Описание

Время

Read from regular class

Чтение атрибута обычного класса

14.1 ns (70.9 млн операций/сек)

Write to regular class

Запись атрибута обычного класса

15.7 ns (63.6 млн операций/сек)

Read from slots class

Чтение атрибута класса с slots

14.1 ns (70.7 млн операций/сек)

Write to slots class

Запись атрибута класса с slots

16.4 ns (60.8 млн операций/сек)

Read from @property

Чтение через @property

19.0 ns (52.8 млн операций/сек)

getattr()

Вызов getattr()

13.8 ns (72.7 млн операций/сек)

hasattr()

Вызов hasattr()

23.8 ns (41.9 млн операций/сек)

JSON - операции

Операция

Описание

Время

json.dumps() (simple)

Сериализация JSON (простой объект)

708 ns (1.4 млн операций/сек)

json.loads() (simple)

Десериализация JSON (простой объект)

714 ns (1.4 млн операций/сек)

json.dumps() (complex)

Сериализация JSON (сложный объект)

2.65 мкс (376.8 тыс. операций/сек)

json.loads() (complex)

Десериализация JSON (сложный объект)

2.22 мкс (449.9 тыс. операций/сек)

orjson.dumps() (complex)

Сериализация orjson (сложный объект)

310 ns (3.2 млн операций/сек)

orjson.loads() (complex)

Десериализация orjson (сложный объект)

839 ns (1.2 млн операций/сек)

ujson.dumps() (complex)

Сериализация ujson (сложный объект)

1.64 мкс (611.2 тыс. операций/сек)

msgspec encode (complex)

Кодирование msgspec (сложный объект)

445 ns (2.2 млн операций/сек)

Pydantic model_dump_json()

Сериализация модели Pydantic в JSON

1.54 мкс (647.8 тыс. операций/сек)

Pydantic model_validate_json()

Валидация и парсинг JSON в модель Pydantic

2.99 мкс (334.7 тыс. операций/сек)

Веб-фреймворки:

Операция

Описание

Время

Flask (return JSON)

Flask (возврат JSON)

16.5 мкс (60.7 тыс. запросов/сек)

Django (return JSON)

Django (возврат JSON)

18.1 мкс (55.4 тыс. запросов/сек)

FastAPI (return JSON)

FastAPI (возврат JSON)

8.63 мкс (115.9 тыс. запросов/сек)

Starlette (return JSON)

Starlette (возврат JSON)

8.01 мкс (124.8 тыс. запросов/сек)

Litestar (return JSON)

Litestar (возврат JSON)

8.19 мкс (122.1 тыс. запросов/сек)

Файловый ввод/вывод:

Операция

Описание

Время

Open and close file

Открыть и закрыть файл

9.05 мкс (110.5 тыс. операций/сек)

Read 1KB file

Чтение файла 1 КБ

10.0 мкс (99.5 тыс. операций/сек)

Write 1KB file

Запись файла 1 КБ

35.1 мкс (28.5 тыс. операций/сек)

Write 1MB file

Запись файла 1 МБ

207 мкс (4.8 тыс. операций/сек)

pickle.dumps()

Сериализация с помощью pickle

1.30 мкс (769.6 тыс. операций/сек)

pickle.loads()

Десериализация с помощью pickle

1.44 мкс (695.2 тыс. операций/сек)

Базы данных:

Операция

Описание

Время

SQLite insert (JSON blob)

Вставка в SQLite (объект JSON как BLOB)

192 мкс (5.2 тыс. операций/сек)

SQLite select by PK

Выборка из SQLite по первичному ключу

3.57 мкс (280.3 тыс. операций/сек)

SQLite update one field

Обновление одного поля в SQLite

5.22 мкс (191.7 тыс. операций/сек)

diskcache set

Запись в diskcache

23.9 мкс (41.8 тыс. операций/сек)

diskcache get

Чтение из diskcache

4.25 мкс (235.5 тыс. операций/сек)

MongoDB insert_one

Вставка одного документа в MongoDB

119 мкс (8.4 тыс. операций/сек)

MongoDB find_one by _id

Поиск одного документа по _id в MongoDB

121 мкс (8.2 тыс. операций/сек)

MongoDB find_one by nested field

Поиск одного документа по вложенному полю в MongoDB

124 мкс (8.1 тыс. операций/сек)

Функции:

Операция

Описание

Время

Empty function call

Вызов пустой функции

22.4 ns (44.6 млн операций/сек)

Function with 5 args

Вызов функции с 5 аргументами

24.0 ns (41.7 млн операций/сек)

Method call

Вызов метода

23.3 ns (42.9 млн операций/сек)

Lambda call

Вызов лямбда-функции

19.7 ns (50.9 млн операций/сек)

try/except (no exception)

Блок try/except без исключения

21.5 ns (46.5 млн операций/сек)

try/except (exception raised)

Блок try/except с выброшенным исключением

139 ns (7.2 млн операций/сек)

isinstance() check

Проверка с помощью isinstance()

18.3 ns (54.7 млн операций/сек)

Асинхронные процессы:

Операция

Описание

Время

Create coroutine object

Создание объекта корутины

47.0 ns (21.3 млн операций/сек)

run_until_complete(empty)

run_until_complete (пустая корутина)

27.6 мкс (36.2 тыс. операций/сек)

asyncio.sleep(0)

asyncio.sleep(0)

39.4 мкс (25.4 тыс. операций/сек)

gather() 10 coroutines

gather() для 10 корутин

55.0 мкс (18.2 тыс. операций/сек)

create_task() + await

create_task() + await

52.8 мкс (18.9 тыс. операций/сек)

async with (context manager)

async with (менеджер контекста)

29.5 мкс (33.9 тыс. операций/сек)

Расходование памяти

Для понимания того, сколько памяти потребляют различные объекты Python.

Пустой процесс Python занимает 15,73 МБ.

Строки

Эмпирическое правило для строк: базовый строковый объект занимает 41 байт, каждый дополнительный символ добавляет по 1 байту.

Строка

Размер

Пустая строка ""

41 байт

Строка из 1 символа "a"

42 байта

Строка из 100 символов

141 байт

Заметны накладные расходы в 41 байт на создание пустой строки
Заметны накладные расходы в 41 байт на создание пустой строки

Числа

Числа в Python оказываются удивительно объёмными. Они обязаны наследоваться от PyObject в CPython и поддерживают подсчёт ссылок для сборки мусора, поэтому их размер значительно превосходит наше привычное представление, каковым являются, например:

  • 2 байта = короткое целое (short int)

  • 4 байта = длинное целое (long int)

  • и т.д.

Тип

Описание

Размер

Small int (0-256, cached)

Малое целое (0–256, кэшированное)

28 байт

Large int (1000)

Большое целое (1000)

28 байт

Very large int (10**100)

Очень большое целое (10**100)

72 байта

Float

Число с плавающей точкой

24 байта

Числа в Python оказываются удивительно объёмными. Что большие, что малые...
Числа в Python оказываются удивительно объёмными. Что большие, что малые...

Коллекции

Коллекции в Python — это очень удобный инструмент: списки, динамически расширяющиеся по мере необходимости, сверхбыстрые словари и множества. Ниже приведены накладные объемы памяти для пустых коллекций и объемы для коллекций, содержащих 1000 элементов.

Коллекция

Описание

Размер пустой коллекции

Размер содержащей 1000 элементов

List (ints)

Список (целые числа)

56 байт

35.2 КБ

List (floats)

Список (числа с плавающей точкой)

56 байт

32.1 КБ

Dict

Словарь

64 байта

63.4 КБ

Set

Множество

216 байт

59.6 КБ

Пустая коллекция занимает места ненамного больше, чем число...
Пустая коллекция занимает места ненамного больше, чем число...

Классы и экземпляры

slots — интересное дополнение к классам Python. Они полностью исключают использование dict для хранения атрибутов и других значений. Даже для одного экземпляра класс с slots оказывается значительно компактнее (212 байт против 694 байт при наличии 5 атрибутов). Если вы храните в памяти большое количество таких объектов — например, в списке или кэше, — экономия памяти за счёт slots становится очень заметной: потребление памяти сокращается более чем в два раза. К счастью, в большинстве случаев достаточно просто добавить slots в определение класса, чтобы значительно сократить расход памяти, приложив при этом минимум усилий.

Тип

Описание

Пустой класс

5 атрибутов

Regular class

Обычный класс

344 байта

694 байта

slots class

Класс с slots

32 байта

212 байт

dataclass

dataclass

694 байта

@dataclass(slots=True)

dataclass с включёнными slots

212 байт

namedtuple

Именованный кортеж

228 байт

Суммарное использование памяти (для 1000 экземпляров):

Тип

Описание

Общий объём памяти

List of 1,000 regular class instances

Список из 1 000 экземпляров обычного класса

165.2 КБ

List of 1,000 slots class instances

Список из 1 000 экземпляров класса со slots

79.1 КБ

Расход памяти на 1000 экземпляров класса (использование слотов в 2 раза сокращает расход памяти!)
Расход памяти на 1000 экземпляров класса (использование слотов в 2 раза сокращает расход памяти!)

Базовые операции

Стоимость базовых операций в Python: значительно медленнее, чем в C/C++/C#, но всё ещё довольно высока. Я добавил краткое сравнение с C# в репозиторий с исходным кодом.

Арифметические

Операция

Описание

Время

Add two integers

Сложение двух целых чисел

19.0 нс (52.7 млн операций/сек)

Add two floats

Сложение двух чисел с плавающей точкой

18.4 нс (54.4 млн операций/сек)

Multiply two integers

Умножение двух целых чисел

19.4 нс (51.6 млн операций/сек)

У всех арифметических операций сопоставимое время...
У всех арифметических операций сопоставимое время...

Операции со строками

Операции со строками в Python также выполняются быстро. f-строки являются самым быстрым способом форматирования, и даже самый медленный стиль всё равно измеряется всего лишь в наносекундах.

Операция

Описание

Время

Concatenation (+)

Конкатенация строк (+)

39.1 нс (25.6 млн операций/сек)

f-string

Форматирование f-строкой

64.9 нс (15.4 млн операций/сек)

.format()

Форматирование через .format()

103 нс (9.7 млн операций/сек)

% formatting

Форматирование через %

89.8 нс (11.1 млн операций/сек)

Использование f-строк в общем случае оптимальнее всего.
Использование f-строк в общем случае оптимальнее всего.

Операции со списками

Операции со списками в Python очень быстрые. Добавление одного элемента обычно занимает около 28 нс — другими словами, можно выполнять около 35 миллионов добавлений в секунду. Это справедливо до тех пор, пока списку не требуется расширение, например, по алгоритму удвоения ёмкости. Эффект такого расширения можно заметить по снижению количества операций в секунду при работе со списками из 1 000 элементов.

Удивительно, но генераторы списков (list comprehensions) на 26 % быстрее эквивалентных циклов for с вызовами append.

Операция

Описание

Время

list.append()

Добавление элемента в список

28.7 нс (34.8 млн операций/сек)

List comprehension (1,000 items)

Генератор списка (1 000 элементов)

9.45 мкс (105.8 тыс. операций/сек)

Equivalent for-loop (1,000 items)

Эквивалентный цикл for (1 000 элементов)

11.9 мкс (83.9 тыс. операций/сек)

Генераторы списка эффективнее цикла for
Генераторы списка эффективнее цикла for

Доступ к коллекциям и итерация

Насколько быстро вы можете извлекать данные из встроенных коллекций Python? Вот яркий пример того, насколько правильная структура данных ускоряет операции: проверка item in set или item in dict оказывается в 200 раз быстрее, чем item in list — и это даже для списка всего из 1 000 элементов!

На графике ниже ось X имеет нелинейный масштаб.

Доступ по ключу / индексу

Операция

Описание

Время

Dict lookup by key

Поиск по ключу в словаре

21.9 нс (45.7 млн операций/сек)

Set membership (in)

Проверка принадлежности элемента множеству

19.0 нс (52.7 млн операций/сек)

List index access

Доступ к элементу списка по индексу

17.6 нс (56.8 млн операций/сек)

List membership (in, 1,000 items)

Проверка принадлежности в списке (1 000 элементов)

3.85 мкс (259.6 тыс. операций/сек)

Списки так же быстры, как и словари и множества, если через индекс. В остальных случаях они очень медленны...
Списки так же быстры, как и словари и множества, если через индекс. В остальных случаях они очень медленны...

Длина объекта

Вызов len() происходит очень быстро. Возможно, всё-таки нет необходимости оптимизировать его удаление из условия цикла while, который выполняется всего 100 раз.

Коллекция

Описание

Время вызова len()

List (1,000 items)

Список (1 000 элементов)

18.8 нс (53.3 млн операций/сек)

Dict (1,000 items)

Словарь (1 000 элементов)

17.6 нс (56.9 млн операций/сек)

Set (1,000 items)

Множество (1 000 элементов)

18.0 нс (55.5 млн операций/сек)

Итерации

Операция

Описание

Время

Iterate 1,000-item list

Итерация по списку из 1000 элементов

7.87 мкс (127.0 тыс. операций/сек)

Iterate 1,000-item dict (keys)

Итерация по ключам словаря из 1000 элементов

8.74 мкс (114.5 тыс. операций/сек)

sum() of 1,000 integers

Суммирование 1000 целых чисел

1.87 мкс (534.8 тыс. операций/сек)

Атрибуты классов и объектов

Стоимость чтения и записи атрибутов, а также то, как на это влияет использование slots. Применение slots позволяет сократить потребление памяти более чем в два раза при хранении больших коллекций объектов, при этом скорость доступа к атрибутам остаётся практически неизменной.

Доступ к атрибутам

Операция

Обычный класс

Класс с slots

Read attribute

14.1 нс (70.9 млн операций/сек)

14.1 нс (70.7 млн операций/сек)

Write attribute

15.7 нс (63.6 млн операций/сек)

16.4 нс (60.8 млн операций/сек)

Скорость доступа к атрибутам со slots остаётся практически неизменной
Скорость доступа к атрибутам со slots остаётся практически неизменной

Другие операции с атрибутами

Операция

Описание

Время

Read @property

Чтение через @property

19.0 нс (52.8 млн операций/сек)

getattr(obj, 'attr')

Вызов getattr(obj, 'attr')

13.8 нс (72.7 млн операций/сек)

hasattr(obj, 'attr')

Вызов hasattr(obj, 'attr')

23.8 нс (41.9 млн операций/сек)

JSON и сериализация

Сравнение стандартной библиотеки JSON с оптимизированными альтернативами. Библиотека orjson поддерживает больше типов данных и работает более чем в 8 раз быстрее, чем стандартный модуль json, при сериализации сложных объектов. Впечатляюще!

Сериализация (dumps)

Библиотека

Простой объект

Сложный объект

json (stdlib)

708 нс (1.4 млн операций/сек)

2.65 мкс (376.8 тыс. операций/сек)

orjson

60.9 нс (16.4 млн операций/сек)

310 нс (3.2 млн операций/сек)

ujson

264 нс (3.8 млн операций/сек)

1.64 мкс (611.2 тыс. операций/сек)

msgspec

92.3 нс (10.8 млн операций/сек)

445 нс (2.2 млн операций/сек)

Потрясающе!
Потрясающе!

Десериализация (loads)

Библиотека

Простой объект

Сложный объект

json (stdlib)

714 нс (1.4 млн операций/сек)

2.22 мкс (449.9 тыс. операций/сек)

orjson

106 нс (9.4 млн операций/сек)

839 нс (1.2 млн операций/сек)

ujson

268 нс (3.7 млн операций/сек)

1.46 мкс (682.8 тыс. операций/сек)

msgspec

101 нс (9.9 млн операций/сек)

850 нс (1.2 млн операций/сек)

Pydantic

Pydantic — это...

Pydantic — это популярная библиотека для Python, предназначенная для валидации данных и управления настройками (конфигурацией) с использованием аннотаций типов (type hints). Она позволяет автоматически проверять, соответствуют ли входные данные ожидаемой структуре и типам, и при необходимости преобразовывать их.

Пример:

from pydantic import BaseModel
from typing import Optional

class User(BaseModel):
    id: int
    name: str
    email: Optional[str] = None

# Автоматическая валидация
user = User(id="1", name="Александр")  # id преобразуется в int
print(user.email)  # None

# Ошибка, если данные неверны:
# User(id="abc", name="...") → ValidationError

Операция

Описание

Время

model_dump_json()

Сериализация модели Pydantic в JSON

1.54 мкс (647.8 тыс. операций/сек)

model_validate_json()

Валидация и парсинг JSON в модель Pydantic

2.99 мкс (334.7 тыс. операций/сек)

model_dump() (to dict)

Преобразование модели Pydantic в словарь

1.71 мкс (585.2 тыс. операций/сек)

model_validate() (from dict)

Валидация словаря и создание модели Pydantic

2.30 мкс (435.5 тыс. операций/сек)

Веб-фреймворки

Возврат простого JSON-ответа. Тестирование производительности выполнено с помощью утилиты wrk на localhost с использованием 4 воркеров в Granian. Каждый фреймворк возвращает один и тот же JSON-ответ из минимального эндпоинта. Доступ к базе данных или подобные операции не используются. Здесь измеряется только собственная накладная нагрузка (overhead) и производительность самого фреймворка. Код, который мы пишем внутри этих view-функций, в основном одинаков.

Результаты

Фреймворк

Запросов в секунду

Задержка (p99)

Flask

60.7 тыс. запросов/сек

20.85 мс (48.0 операций/сек)

Django

55.4 тыс. запросов/сек

170.3 мс (5.9 операций/сек)

FastAPI

115.9 тыс. запросов/сек

1.530 мс (653.6 операций/сек)

Starlette

124.8 тыс. запросов/сек

930 мкс (1.1 тыс. операций/сек)

Litestar

122.1 тыс. запросов/сек

1.010 мс (990.1 операций/сек)

Джанго, подкинь дровишек!..
Джанго, подкинь дровишек!..

Файловый ввод-вывод

Чтение и запись файлов различного размера. Обратите внимание, что график имеет нелинейную шкалу по оси Y.

Базовые операции

Операция

Описание

Время

Open and close (no read)

Открыть и закрыть файл (без чтения)

9.05 мкс (110.5 тыс. операций/сек)

Read 1KB file

Чтение файла размером 1 КБ

10.0 мкс (99.5 тыс. операций/сек)

Read 1MB file

Чтение файла размером 1 МБ

33.6 мкс (29.8 тыс. операций/сек)

Write 1KB file

Запись файла размером 1 КБ

35.1 мкс (28.5 тыс. операций/сек)

Write 1MB file

Запись файла размером 1 МБ

207 мкс (4.8 тыс. операций/сек)

Запись предсказуемо длиннее чтения...
Запись предсказуемо длиннее чтения...

Pickle против JSON при работе с диском

Операция

Описание

Время

pickle.dumps() (complex obj)

Сериализация сложного объекта с помощью pickle

1.30 мкс (769.6 тыс. операций/сек)

pickle.loads() (complex obj)

Десериализация сложного объекта с помощью pickle

1.44 мкс (695.2 тыс. операций/сек)

json.dumps() (complex obj)

Сериализация сложного объекта в JSON

2.72 мкс (367.1 тыс. операций/сек)

json.loads() (complex obj)

Десериализация сложного объекта из JSON

2.35 мкс (425.9 тыс. операций/сек)

Базы данных и персистентность

Сравнение SQLite, diskcache и MongoDB с использованием одного и того же сложного объекта.

Тестовый объект:

user_data = {
    "id": 12345,
    "username": "alice_dev",
    "email": "alice@example.com",
    "profile": {
        "bio": "Software engineer who loves Python",
        "location": "Portland, OR",
        "website": "https://alice.dev",
        "joined": "2020-03-15T08:30:00Z"
    },
    "posts": [
        {"id": 1, "title": "First Post", "tags": ["python", "tutorial"], "views": 1520},
        {"id": 2, "title": "Second Post", "tags": ["rust", "wasm"], "views": 843},
        {"id": 3, "title": "Third Post", "tags": ["python", "async"], "views": 2341},
    ],
    "settings": {
        "theme": "dark",
        "notifications": True,
        "email_frequency": "weekly"
    }
}

SQLite (подход с хранением JSON-объекта как BLOB)

Операция

Описание

Время

Insert one object

Вставка одного объекта

192 мкс (5.2 тыс. операций/сек)

Select by primary key

Выборка по первичному ключу

3.57 мкс (280.3 тыс. операций/сек)

Update one field

Обновление одного поля

5.22 мкс (191.7 тыс. операций/сек)

Delete

Удаление записи

191 мкс (5.2 тыс. операций/сек)

Select with json_extract()

Выборка с использованием json_extract()

4.27 мкс (234.2 тыс. операций/сек)

diskcache

diskcache — это...

diskcache — это высокопроизводительная библиотека на Python для кэширования данных на диске (в отличие от оперативной памяти, как в functools.lru_cache или redis без персистентности). Она предоставляет простой, но мощный интерфейс, похожий на словарь (dict), и предназначена для долгосрочного хранения вычислительно дорогих или часто используемых данных между запусками программы.

import diskcache as dc
cache = dc.Cache('/tmp/mycache')
cache['key'] = 'value'
print(cache['key'])  # 'value'
import diskcache
import time

cache = diskcache.Cache('my_cache')

@cache.memoize(typed=True, expire=3600)
def slow_function(x):
    time.sleep(1)
    return x ** 2

print(slow_function(5))  # ~1 секунда
print(slow_function(5))  # мгновенно (из кэша)

Операция

Описание

Время

cache.set(key, obj)

Запись объекта в кэш

23.9 мкс (41.8 тыс. операций/сек)

cache.get(key)

Чтение объекта из кэша

4.25 мкс (235.5 тыс. операций/сек)

cache.delete(key)

Удаление ключа из кэша

51.9 мкс (19.3 тыс. операций/сек)

Check key exists

Проверка существования ключа

1.91 мкс (523.2 тыс. операций/сек)

MongoDB

Операция

Описание

Время

insert_one()

Вставка одного документа

119 мкс (8.4 тыс. операций/сек)

find_one() by _id

Поиск одного документа по _id

121 мкс (8.2 тыс. операций/сек)

find_one() by nested field

Поиск одного документа по вложенному полю

124 мкс (8.1 тыс. операций/сек)

update_one()

Обновление одного документа

115 мкс (8.7 тыс. операций/сек)

delete_one()

Удаление одного документа

30.4 нс (32.9 млн операций/сек)

Сравнение

Операция

Описание

SQLite

diskcache

MongoDB

Write one object

Запись одного объекта

192 мкс (5.2 тыс. операций/сек)

23.9 мкс (41.8 тыс. операций/сек)

119 мкс (8.4 тыс. операций/сек)

Read by key/id

Чтение по ключу / _id

3.57 мкс (280.3 тыс. операций/сек)

4.25 мкс (235.5 тыс. операций/сек)

121 мкс (8.2 тыс. операций/сек)

Read by nested field

Чтение по вложенному полю

4.27 мкс (234.2 тыс. операций/сек)

N/A

124 мкс (8.1 тыс. операций/сек)

Update one field

Обновление одного поля

5.22 мкс (191.7 тыс. операций/сек)

23.9 мкс (41.8 тыс. операций/сек)

115 мкс (8.7 тыс. операций/сек)

Delete

Удаление

191 мкс (5.2 тыс. операций/сек)

51.9 мкс (19.3 тыс. операций/сек)

30.4 нс (32.9 млн операций/сек)

Примечание: MongoDB работает медленнее из-за сетевого доступа по сравнению с внутрипроцессным доступом.

В SQLite вставка долгая, зато выборка быстрая...
В SQLite вставка долгая, зато выборка быстрая...

Накладные расходы на функции и вызовы

Скрытая стоимость вызовов функций, исключений и асинхронных операций.

Вызовы функций

Операция

Описание

Время

Empty function call

Вызов пустой функции

22.4 нс (44.6 млн операций/сек)

Function with 5 arguments

Вызов функции с 5 аргументами

24.0 нс (41.7 млн операций/сек)

Method call on object

Вызов метода объекта

23.3 нс (42.9 млн операций/сек)

Lambda call

Вызов лямбда-функции

19.7 нс (50.9 млн операций/сек)

Built-in function (len())

Вызов встроенной функции (len())

17.1 нс (58.4 млн операций/сек)

Исключения (Exceptions)

Операция

Описание

Время

try/except (no exception raised)

Блок try/except без выброса исключения

21.5 нс (46.5 млн операций/сек)

try/except (exception raised)

Блок try/except с выброшенным исключением

139 нс (7.2 млн операций/сек)

Проверка типа

Операция

Описание

Время

isinstance()

Проверка типа с помощью isinstance()

18.3 нс (54.7 млн операций/сек)

type() == type

Проверка типа с помощью сравнения type()

21.8 нс (46.0 млн операций/сек)

Накладные расходы асинхронности

Стоимость использования асинхронной механики.

Создание корутин

Операция

Описание

Время

Create coroutine object (no await)

Создание объекта корутины (без await)

47.0 нс (21.3 млн операций/сек)

Create coroutine (with return value)

Создание корутины (с возвращаемым значением)

45.3 нс (22.1 млн операций/сек)

Запуск корутин

Операция

Описание

Время

run_until_complete(empty)

Выполнение пустой корутины через run_until_complete

27.6 мкс (36.2 тыс. операций/сек)

run_until_complete(return value)

Выполнение корутины с возвратом значения

26.6 мкс (37.5 тыс. операций/сек)

Run nested await

Выполнение вложенного await

28.9 мкс (34.6 тыс. операций/сек)

Run 3 sequential awaits

Последовательное выполнение трёх await

27.9 мкс (35.8 тыс. операций/сек)

asyncio.sleep()

Операция

Описание

Время

asyncio.sleep(0)

Вызов asyncio.sleep(0)

39.4 мкс (25.4 тыс. операций/сек)

Coroutine with sleep(0)

Корутина с await asyncio.sleep(0)

41.8 мкс (23.9 тыс. операций/сек)

asyncio.gather()

Операция

Описание

Время

gather() 5 coroutines

Параллельное выполнение 5 корутин через gather()

49.7 мкс (20.1 тыс. операций/сек)

gather() 10 coroutines

Параллельное выполнение 10 корутин через gather()

55.0 мкс (18.2 тыс. операций/сек)

gather() 100 coroutines

Параллельное выполнение 100 корутин через gather()

155 мкс (6.5 тыс. операций/сек)

Создание задач (Task Creation)

Операция

Описание

Время

create_task() + await

Создание задачи через create_task() и ожидание её завершения

52.8 мкс (18.9 тыс. операций/сек)

Create 10 tasks + gather

Создание 10 задач и их одновременное выполнение через gather()

85.5 мкс (11.7 тыс. операций/сек)

Асинхронные контекстные менеджеры и итерация

Операция

Описание

Время

async with (context manager)

Использование асинхронного контекстного менеджера

29.5 мкс (33.9 тыс. операций/сек)

async for (5 items)

Асинхронная итерация по 5 элементам

30.0 мкс (33.3 тыс. операций/сек)

async for (100 items)

Асинхронная итерация по 100 элементам

36.4 мкс (27.5 тыс. операций/сек)

Сравнение синхронного и асинхронного кода

Операция

Описание

Время

Sync function call

Вызов синхронной функции

20.3 нс (49.2 млн операций/сек)

Async equivalent (run_until_complete)

Эквивалентная асинхронная корутина, запущенная через run_until_complete

28.2 мкс (35.5 тыс. операций/сек)

Методология

Подход к бенчмаркингу

  • Все тесты запускались многократно; «прогрев» (warmup) не учитывался во времени.

  • Для измерения времени использовались timeit или perf_counter_ns в зависимости от контекста.

  • Потребление памяти оценивалось с помощью sys.getsizeof() и tracemalloc.

  • Итоговые результаты — медианные значения из N запусков.

Среда выполнения

  • ОС: macOS 26.2

  • Python: 3.14.2 (CPython)

  • Процессор: ARM, 14 ядер (14 логических)

  • Оперативная память: 24.0 ГБ

Репозиторий с кодом

Весь код бенчмарков доступен по ссылке:

https://github.com/mkennedy/python-numbers-everyone-should-know

Выводы

  • Накладные расходы памяти: Объекты Python имеют значительный объём служебной памяти — даже пустой список занимает 56 байт.

  • Скорость dict/set: Поиск в словарях и множествах чрезвычайно быстр (в среднем O(1)), в то время как проверка вхождения в списке — O(n) и на практике в сотни раз медленнее.

  • Производительность JSON: Альтернативные библиотеки (orjson, msgspec) работают в 3–8 раз быстрее стандартного модуля json.

  • Накладные расходы async: Создание и ожидание корутин имеет измеримую задержку — асинхронность стоит применять только тогда, когда действительно нужна конкурентность (например, при I/O).

  • Эффект от slots: Использование slots позволяет сократить потребление памяти более чем в 2 раза для коллекций объектов при практически нулевом влиянии на скорость доступа к атрибутам.

Комментарии (8)


  1. 0xC0CAC01A
    02.01.2026 19:03

    Мне одному кажется, что если вам важны миллисекунды, то вы будете писать не на Питоне?


    1. Akon32
      02.01.2026 19:03

      Надо же знать точку, когда пора переходить на Rust (С++).


  1. Akon32
    02.01.2026 19:03

    Информация полезная, но повторяется по нескольку раз.


    1. hawkinsweirdos
      02.01.2026 19:03

      согласно школьной программе


  1. sami777
    02.01.2026 19:03

    Прям интересно стало узнать о диапазоне значений, которые принимают числа, размерами в десятки байт! Они такие большие или там просто много оверхеда поверх объектов, которые позволяют создавать эти значения. P. S. AI говорит, что для числа, например, Small int, структура которого имеет размер 28 байт полезные данные только 4 байта, т. е. это обычный int на 32 битной машине.


    1. avshkol Автор
      02.01.2026 19:03

      В питоновской логике все 28 байт у числа полезные, ведь это объект со своими свойствами.


  1. i-netay
    02.01.2026 19:03

    Интересно, в какой момент складывать float стало быстрее, чем int. С момента перехода на Python разве что. На уровне операций без питоновских обёрток в том же C сравнение в другую сторону сильно.


  1. supremum76
    02.01.2026 19:03

    Питон это инструмент оркестровки специализированных компонент. Любое иное его использование в продуктовой среде, это ошибка или вынужденное зло.

    Примеры нормального использования:

    • DAG в Airflow

    • Cкрипт, 99% времени которого приходится на выполнение методов ML-библиотеки (scikit-learn, TensorFlow, PyTorch и др.)

    • Скрипт Spark application

    • Задачи перекладывания данных. Типа взять данные от одного компонента, изменить формат и отдать в другой к компонент. В таких задачах 99% времени тратиться на передачу по сети, работы с файлами или базой данных.

    • Разные утилитные скрипты для администрирования систем. Например, скрипты CI/CD.

    • Разовые скрипты обработки файлов. Ну там, убрать из csv особые символы, которые модуль импорта в БД не может обработать. Распарсить файл архива электронных писем и затем положить их в БД.

    • UDF функции, для расширения состава функций БД, где не хватает возможностей родного языка программирования БД.

    От версии к версии Python затраты на операции могут значительно меняться. Тем более сильно может все измениться, если вы используете "ускорители" типа PyPy или Numba.
    Поэтому главное, чтобы код выглядел хорошо (главное, понятно выглядело), без явно неоптимальных конструкций. Типа, где можно циклом или itertools посчитать, не надо рекурсию использовать.