From e630b64418786dffbb2d4216cc0dbe26bf10bea0 Mon Sep 17 00:00:00 2001 From: Pieter Eendebak Date: Fri, 27 Jun 2025 08:56:32 +0200 Subject: [PATCH 1/3] Avoid locks are and refcounts in frozenset operatins --- Objects/setobject.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/Objects/setobject.c b/Objects/setobject.c index 8aa6b0d180907b..cf557d1768ca6f 100644 --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -85,6 +85,8 @@ set_lookkey(PySetObject *so, PyObject *key, Py_hash_t hash) int probes; int cmp; + int frozenset = PyFrozenSet_CheckExact(so); + while (1) { entry = &so->table[i]; probes = (i + LINEAR_PROBES <= mask) ? LINEAR_PROBES: 0; @@ -101,9 +103,14 @@ set_lookkey(PySetObject *so, PyObject *key, Py_hash_t hash) && unicode_eq(startkey, key)) return entry; table = so->table; - Py_INCREF(startkey); - cmp = PyObject_RichCompareBool(startkey, key, Py_EQ); - Py_DECREF(startkey); + if (frozenset) { + cmp = PyObject_RichCompareBool(startkey, key, Py_EQ); + } else { + // incref startkey because it can be removed from the set by the compare + Py_INCREF(startkey); + cmp = PyObject_RichCompareBool(startkey, key, Py_EQ); + Py_DECREF(startkey); + } if (cmp < 0) return NULL; if (table != so->table || entry->key != startkey) @@ -2234,10 +2241,16 @@ set_contains_lock_held(PySetObject *so, PyObject *key) int _PySet_Contains(PySetObject *so, PyObject *key) { + assert(so); + int rv; - Py_BEGIN_CRITICAL_SECTION(so); - rv = set_contains_lock_held(so, key); - Py_END_CRITICAL_SECTION(); + if (PyFrozenSet_CheckExact(so)) { + rv = set_contains_lock_held(so, key); + } else { + Py_BEGIN_CRITICAL_SECTION(so); + rv = set_contains_lock_held(so, key); + Py_END_CRITICAL_SECTION(); + } return rv; } From 40d2d2917f66abeb5477d925cbb65a7bd65f5cba Mon Sep 17 00:00:00 2001 From: Pieter Eendebak Date: Sun, 29 Jun 2025 22:28:39 +0200 Subject: [PATCH 2/3] avoid table check --- Objects/setobject.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Objects/setobject.c b/Objects/setobject.c index cf557d1768ca6f..a07aad4134f752 100644 --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -105,16 +105,18 @@ set_lookkey(PySetObject *so, PyObject *key, Py_hash_t hash) table = so->table; if (frozenset) { cmp = PyObject_RichCompareBool(startkey, key, Py_EQ); + if (cmp < 0) + return NULL; } else { // incref startkey because it can be removed from the set by the compare Py_INCREF(startkey); cmp = PyObject_RichCompareBool(startkey, key, Py_EQ); Py_DECREF(startkey); + if (cmp < 0) + return NULL; + if (table != so->table || entry->key != startkey) + return set_lookkey(so, key, hash); } - if (cmp < 0) - return NULL; - if (table != so->table || entry->key != startkey) - return set_lookkey(so, key, hash); if (cmp > 0) return entry; mask = so->mask; From 10aed735ea78e47731ce6c9a1ff0dd3df14d5fe8 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Wed, 9 Jul 2025 21:27:18 +0000 Subject: [PATCH 3/3] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../2025-07-09-21-27-14.gh-issue-132657.kSA8R3.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2025-07-09-21-27-14.gh-issue-132657.kSA8R3.rst diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-07-09-21-27-14.gh-issue-132657.kSA8R3.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-07-09-21-27-14.gh-issue-132657.kSA8R3.rst new file mode 100644 index 00000000000000..99f7a990875a0a --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-07-09-21-27-14.gh-issue-132657.kSA8R3.rst @@ -0,0 +1 @@ +Improve performance of :class:`frozenset` by removing locks in the free-threading build.