Содержание
Весь секрет в оптимизации и избавлении от гигантского switch на C
Команда CPython продолжает ускорять Python. Так, релиз 3.14 уже включает одну из самых заметных внутренних реформ — новый байт-кодовый интерпретатор.
Благодаря этому улучшению в некоторых случаях производительность увеличивается до 30%, при этом средний прирост оценивается в 3–5%.
Что поменялось?
В старых версиях интерпретатор Python представлял собой один огромный switch
на C, который последовательно перебирал инструкции (opcodes) и выполнял соответствующий код.
В новой версии каждая инструкция теперь обрабатывается отдельной мини-функцией, а переходы между ними реализованы через tail calls — особый тип вызова функции, при котором стек вызовов не увеличивается.
Что такое tail call?
Tail call (или «хвостовой вызов») — это вызов функции как последнее действие в другой функции.
Пример:
def greet(): return say_hello() # Это tail call
В языках, поддерживающих tail call optimization (например, Scheme или Scala), при таком вызове не создается новая запись в стеке — используется текущая. Это экономит память и предотвращает переполнение стека при глубокой рекурсии.
Важно: Python 3.14 не поддерживает оптимизацию хвостовых вызовов для самого Python-кода. Tail calls используются внутри интерпретатора, на уровне C-кода.
Зачем это нужно?
Tail calls позволяют:
- Лучше использовать кеш процессора;
- Уменьшить накладные расходы на переход между операциями;
- Позволить компилятору (например, Clang 19+) оптимизировать код эффективнее, чем при использовании большого switch-блока;
- Разгрузить пайплайн CPU, особенно на современных архитектурах.
Эта техника делает интерпретатор легче и быстрее. Причем, что важно, без изменений в Python-коде разработчиков.
Какие результаты?
На ранних тестах Python 3.14 показывает:
- До 30% ускорения в некоторых нагрузках;
- В среднем +3–5% к производительности без изменения кода;
- Отличную компиляцию и предсказуемость исполнения при использовании Clang 19 и выше.
А что насчет Cython, PyPy и tail call optimization?
- Cython по-прежнему не поддерживает оптимизацию хвостовых вызовов.
- PyPy реализует свои методы ускорения, но пока также не делает TCO.
- В самом Python хвостовая рекурсия по-прежнему вызывает
RecursionError
, если стек переполнен.
Нужно ли что-то менять в коде?
Нет. Это внутренняя оптимизация интерпретатора CPython, и она работает прозрачно для разработчиков.