mirror of
https://github.com/python/cpython.git
synced 2026-04-20 02:40:59 +00:00
gh-95004: specialize access to enums and fix scaling on free-threading (#148184)
Co-authored-by: Ken Jin <kenjin4096@gmail.com>
This commit is contained in:
parent
7e0a0be409
commit
e371ce10cd
4 changed files with 54 additions and 8 deletions
|
|
@ -2047,5 +2047,25 @@ def load_module_attr_missing():
|
|||
sys.modules.pop("test_module_with_getattr", None)
|
||||
|
||||
|
||||
@cpython_only
|
||||
@requires_specialization
|
||||
def test_load_attr_enum(self):
|
||||
import enum
|
||||
|
||||
class Color(enum.IntEnum):
|
||||
RED = 1
|
||||
GREEN = 2
|
||||
BLUE = 3
|
||||
|
||||
def load_enum_member():
|
||||
for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
|
||||
x = Color.RED
|
||||
assert x == 1
|
||||
|
||||
load_enum_member()
|
||||
self.assert_specialized(load_enum_member,
|
||||
"LOAD_ATTR_CLASS_WITH_METACLASS_CHECK")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
The specializing interpreter now specializes for :class:`enum.Enum` improving performance and scaling in free-threading. Patch by Kumar Aditya.
|
||||
|
|
@ -1201,22 +1201,33 @@ specialize_class_load_attr(PyObject *owner, _Py_CODEUNIT *instr,
|
|||
}
|
||||
}
|
||||
switch (kind) {
|
||||
case METHOD:
|
||||
case NON_DESCRIPTOR:
|
||||
#ifdef Py_GIL_DISABLED
|
||||
if (!_PyObject_HasDeferredRefcount(descr)) {
|
||||
SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_DESCR_NOT_DEFERRED);
|
||||
case MUTABLE:
|
||||
// special case for enums which has Py_TYPE(descr) == cls
|
||||
// so guarding on type version is sufficient
|
||||
if (Py_TYPE(descr) != cls) {
|
||||
SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_MUTABLE_CLASS);
|
||||
Py_XDECREF(descr);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
write_u32(cache->type_version, tp_version);
|
||||
if (Py_TYPE(descr)->tp_descr_get || Py_TYPE(descr)->tp_descr_set) {
|
||||
SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_OVERRIDING_DESCRIPTOR);
|
||||
Py_XDECREF(descr);
|
||||
return -1;
|
||||
}
|
||||
_Py_FALLTHROUGH;
|
||||
case METHOD:
|
||||
case NON_DESCRIPTOR:
|
||||
#ifdef Py_GIL_DISABLED
|
||||
maybe_enable_deferred_ref_count(descr);
|
||||
#endif
|
||||
write_ptr(cache->descr, descr);
|
||||
if (metaclass_check) {
|
||||
write_u32(cache->keys_version, meta_version);
|
||||
write_u32(cache->keys_version, tp_version);
|
||||
write_u32(cache->type_version, meta_version);
|
||||
specialize(instr, LOAD_ATTR_CLASS_WITH_METACLASS_CHECK);
|
||||
}
|
||||
else {
|
||||
write_u32(cache->type_version, tp_version);
|
||||
specialize(instr, LOAD_ATTR_CLASS);
|
||||
}
|
||||
Py_XDECREF(descr);
|
||||
|
|
|
|||
|
|
@ -295,6 +295,20 @@ def setattr_non_interned():
|
|||
setattr(obj, f"{prefix}_c", None)
|
||||
|
||||
|
||||
from enum import Enum
|
||||
class MyEnum(Enum):
|
||||
X = 1
|
||||
Y = 2
|
||||
Z = 3
|
||||
|
||||
@register_benchmark
|
||||
def enum_attr():
|
||||
for _ in range(1000 * WORK_SCALE):
|
||||
MyEnum.X
|
||||
MyEnum.Y
|
||||
MyEnum.Z
|
||||
|
||||
|
||||
def bench_one_thread(func):
|
||||
t0 = time.perf_counter_ns()
|
||||
func()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue