GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | ||||||||||||||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | ||||||||||||||||||||||||||||
GeezerVison is showing github.com — pickle.dumps() creates and discards an AttributeError on every call since 3.13.1 · Issue #158126 · python/cpython Closed Closed Copy link Labels 3.14bugs and security fixesbugs and security fixes3.15bugs and security fixesbugs and security fixes3.16new features, bugs and security fixesnew features, bugs and security fixesextension-modulesC modules in the Modules dirC modules in the Modules dirtype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error DescriptionBug reportBug description:Since gh-125631 (GH-125752, backported to 3.13 in GH-126528),
https://github.com/python/cpython/blob/a5a4659548e/Modules/_pickle.c#L4862-L4867 A plain The cost is visible with plain import io import pickle import timeit p = pickle.Pickler(io.BytesIO()) class C: pass c = C() cases = [ ('getattr(pickler, "reducer_override", None)', lambda: getattr(p, 'reducer_override', None)), cases = [ ('getattr(pickler, "reducer_override", None)', lambda: getattr(p, 'reducer_override', None)), ('getattr(pickler, "fast", None)', lambda: getattr(p, 'fast', None)), ('getattr(c, "reducer_override", None)', lambda: getattr(c, 'reducer_override', None)), ('pickle.dumps(None)', lambda: pickle.dumps(None)), ] for label, f in cases: t = timeit.Timer(f) n, _ = t.autorange() print(f'{min(t.repeat(7, n)) / n * 1e9:8.1f} ns {label}') On main (a5a4659, A missing attribute costs about 40 ns on a regular object and about 330 ns on a
+static PyObject *Pickler_getattr(PyObject *self, PyObject *name); + static int dump(PickleState *state, PicklerObject *self, PyObject *obj) { @@ /* Cache the reducer_override method, if it exists. */ - if (PyObject_GetOptionalAttr((PyObject *)self, &_Py_ID(reducer_override), - &tmp) < 0) { + if (Py_TYPE(self)->tp_getattro == Pickler_getattr) { + tmp = _PyObject_GenericGetAttrWithDict((PyObject *)self, + &_Py_ID(reducer_override), + NULL, 1); + if (tmp == NULL && PyErr_Occurred()) { + goto error; + } + } + else if (PyObject_GetOptionalAttr((PyObject *)self, + &_Py_ID(reducer_override), &tmp) < 0) { goto error; } With this change (only the
The same pattern exists in
This is similar to gh-157840, where I found this while profiling CPython versions tested on:CPython main branch, 3.16, 3.15, 3.14, 3.13 Operating systems tested on:Linux Linked PRs
Activity
MetadataMetadataAssigneesLabels3.14bugs and security fixesbugs and security fixes3.15bugs and security fixesbugs and security fixes3.16new features, bugs and security fixesnew features, bugs and security fixesextension-modulesC modules in the Modules dirC modules in the Modules dirtype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error Projects
MilestoneRelationshipsDevelopmentIssue actions | ||||||||||||||||||||||||||||
| You are visitor 01402520 — GeezerVison does not store the pages you look up. Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required. |