From a8c2e4492a8d0bf32a8cf10edc13d38d428f6b7b Mon Sep 17 00:00:00 2001 From: Sam Gross Date: Thu, 9 Jan 2025 20:38:38 +0000 Subject: [PATCH 1/2] gh-128691: Use deferred reference counting on `_thread._local` This change, along with the LOAD_ATTR specializations, makes the "thread_local_read" micro benchmark in Tools/ftscalingbench/ftscalingbench.py scale well to multiple threads. --- Modules/_threadmodule.c | 1 + 1 file changed, 1 insertion(+) diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c index 2cbdfeb09b95ae..3b7ba514864042 100644 --- a/Modules/_threadmodule.c +++ b/Modules/_threadmodule.c @@ -1435,6 +1435,7 @@ local_new(PyTypeObject *type, PyObject *args, PyObject *kw) Py_DECREF(localsdict); Py_DECREF(sentinel_wr); + _PyObject_SetDeferredRefcount((PyObject *)self); return (PyObject *)self; err: From a0bcabcd827d2e8bd0a02a5813af17b34e2a53b2 Mon Sep 17 00:00:00 2001 From: Sam Gross Date: Fri, 10 Jan 2025 00:01:36 +0000 Subject: [PATCH 2/2] Move _PyObject_SetDeferredRefcount call up --- Modules/_threadmodule.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c index 3b7ba514864042..d19ae326bd6b48 100644 --- a/Modules/_threadmodule.c +++ b/Modules/_threadmodule.c @@ -1414,6 +1414,10 @@ local_new(PyTypeObject *type, PyObject *args, PyObject *kw) return NULL; } + // gh-128691: Use deferred reference counting for thread-locals to avoid + // contention on the shared object. + _PyObject_SetDeferredRefcount((PyObject *)self); + self->args = Py_XNewRef(args); self->kw = Py_XNewRef(kw); @@ -1435,7 +1439,6 @@ local_new(PyTypeObject *type, PyObject *args, PyObject *kw) Py_DECREF(localsdict); Py_DECREF(sentinel_wr); - _PyObject_SetDeferredRefcount((PyObject *)self); return (PyObject *)self; err: