https://github.com/python/cpython/commit/6fb51f23f7973560c009552c61e86955584a2fb2 commit: 6fb51f23f7973560c009552c61e86955584a2fb2 branch: main author: John <[email protected]> committer: ZeroIntensity <[email protected]> date: 2026-07-22T18:43:18-04:00 summary:
gh-154401: Skip fetching the thread state for non-GC types in `_Py_Dealloc` (GH-154430) _Py_Dealloc() fetched the current thread state and computed the C recursion margin on every deallocation, but both are only used by the trashcan mechanism, which applies only to GC-tracked types. Gate them behind the Py_TPFLAGS_HAVE_GC check so the common non-GC case (int, float, str and similar atomic types) skips them. On platforms where _PyThreadState_GET() reads a _Thread_local via a function call (e.g. macOS TLV), this removes a call from every non-GC deallocation. Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]> files: A Misc/NEWS.d/next/Core_and_Builtins/2026-07-22-14-30-00.gh-issue-154429.Qk9mZ2.rst M Objects/object.c diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-07-22-14-30-00.gh-issue-154429.Qk9mZ2.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-07-22-14-30-00.gh-issue-154429.Qk9mZ2.rst new file mode 100644 index 00000000000000..04781b03356b9f --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-07-22-14-30-00.gh-issue-154429.Qk9mZ2.rst @@ -0,0 +1,2 @@ +Slightly speed up deallocation of objects that are not tracked by the garbage +collector, such as :class:`int`, :class:`float` and :class:`str`. diff --git a/Objects/object.c b/Objects/object.c index bd23c2e2388194..fadd9273a36607 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -3292,13 +3292,20 @@ _Py_Dealloc(PyObject *op) PyTypeObject *type = Py_TYPE(op); unsigned long gc_flag = type->tp_flags & Py_TPFLAGS_HAVE_GC; destructor dealloc = type->tp_dealloc; - PyThreadState *tstate = _PyThreadState_GET(); - intptr_t margin = _Py_RecursionLimit_GetMargin(tstate); - if (margin < 2 && gc_flag) { - _PyTrash_thread_deposit_object(tstate, (PyObject *)op); - return; + PyThreadState *tstate = NULL; + intptr_t margin = 0; + if (gc_flag) { + tstate = _PyThreadState_GET(); + margin = _Py_RecursionLimit_GetMargin(tstate); + if (margin < 2) { + _PyTrash_thread_deposit_object(tstate, (PyObject *)op); + return; + } } #ifdef Py_DEBUG + if (tstate == NULL) { + tstate = _PyThreadState_GET(); + } #if !defined(Py_GIL_DISABLED) && !defined(Py_STACKREF_DEBUG) /* This assertion doesn't hold for the free-threading build, as * PyStackRef_CLOSE_SPECIALIZED is not implemented */ @@ -3340,7 +3347,7 @@ _Py_Dealloc(PyObject *op) Py_XDECREF(old_exc); Py_DECREF(type); #endif - if (tstate->delete_later && margin >= 4 && gc_flag) { + if (gc_flag && tstate->delete_later && margin >= 4) { _PyTrash_thread_destroy_chain(tstate); } } _______________________________________________ Python-checkins mailing list -- [email protected] To unsubscribe send an email to [email protected] https://mail.python.org/mailman3//lists/python-checkins.python.org Member address: [email protected]
