`LOAD_CONST` разделили на три опкода в 3.14https://github.com/python/cpython/pull/125972
В Python 3.14 распилили один из самых популярных опкодов:
LOAD_CONST
. Он, как можно понять из названия, он загружал константы из
frame->co_consts
:
// 3.13:
pure inst(LOAD_CONST, (-- value)) {
value = GETITEM(FRAME_CO_CONSTS, oparg);
Py_INCREF(value);
}
>>> def func():
... return 1
>>> func.__code__.co_consts
(None, 1)
Теперь
LOAD_CONST
разделен на:
-
LOAD_SMALL_INT
для интов в
range(256)
-
LOAD_CONST_IMMORTAL
для загрузки бесмертных объектов (на 1
Py_INCREF
меньше, см
PyStackRef_FromPyObjectNew
vs `PyStackRef_FromPyObjectImmortal`)
-
LOAD_CONST
для оставшихся
А еще и
RETURN_CONST
удалили под шумок.
И вот демо байткода:
>>> import dis
>>> def func():
... x = 1
... y = ...
... z = 'привет, мир'
>>> dis.dis(func, adaptive=True)
2 LOAD_SMALL_INT 1
STORE_FAST 0 (x)
3 LOAD_CONST 1 (Ellipsis)
STORE_FAST 1 (y)
4 LOAD_CONST 2 ('привет, мир')
STORE_FAST 2 (z)
LOAD_CONST 0 (None)
RETURN_VALUE
>>> # Create caches for tier1 adaptive interpreter to work:
>>> for _ in range(100):
... func()
>>> dis.dis(func, adaptive=True)
2 LOAD_SMALL_INT 1
STORE_FAST 0 (x)
3 LOAD_CONST_IMMORTAL 1 (Ellipsis)
STORE_FAST 1 (y)
4 LOAD_CONST 2 ('привет, мир')
STORE_FAST 2 (z)
LOAD_CONST_IMMORTAL 0 (None)
RETURN_VALUE
Зачем нужен LOAD_SMALL_INT?https://github.com/python/cpython/issues/101291
Если вы внимательно смотрели мой видос про int, то вы помните, как выглядят инты внутри питона:
typedef struct _PyLongValue {
uintptr_t lv_tag; /* Number of digits, sign and flags */
digit ob_digit[1];
} _PyLongValue;
struct _longobject {
PyObject_HEAD
_PyLongValue long_value;
};
Большие и сложные объекты. Но, для очень частых маленьких чисел, такое переусложнение замедляет работу. Мы можем просто представлять числа в рамках одного машинного слова и складывать их сразу в oparg, без необходимости заргужать их из
co_consts
:
op(_LOAD_SMALL_INT, (-- value)) {
PyObject *val = PyLong_FromLong(this_instr->oparg);
value = sym_new_const(ctx, val);
}
В Python2, кстати, работало быстрее, потому что там был честный
int
тип.
ОбсуждениеЗадумываетесь ли вы про подобные микро-оптимизации, когда пишите код?