https://github.com/python/cpython/commit/cdf010b10c673e1ec4faaf3f8f9be39237986880
commit: cdf010b10c673e1ec4faaf3f8f9be39237986880
branch: main
author: he_tao <[email protected]>
committer: methane <[email protected]>
date: 2026-10-18T23:36:02+09:00
summary:

gh-158816: Skip useless hash table probe when deleting from split dicts 
(#158819)

delitem_common() unconditionally called lookdict_index() to locate the index 
slot in dk_indices that points at the entry being removed.

That slot is only used by the combined branch, to overwrite it with DKIX_DUMMY. 
 In split tables the whole probe sequence was redundant work.

Move the call into the combined branch and drop the now-pointless assert() for 
split tables.

Microbenchmark (free-threaded build, -Og, no PGO; deleting keys from 
materialized instance dicts; medians over 12 alternating runs):

    del d[k]           71.2 -> 69.2 ns/op   (-2.8%)
    d.pop(k)           98.9 -> 96.1 ns/op   (-2.8%)
    colliding hashes   78.0 -> 74.4 ns/op   (-4.6%)

files:
A 
Misc/NEWS.d/next/Core_and_Builtins/2026-10-04-20-04-55.gh-issue-158816.9ulhWb.rst
M Objects/dictobject.c

diff --git 
a/Misc/NEWS.d/next/Core_and_Builtins/2026-10-04-20-04-55.gh-issue-158816.9ulhWb.rst
 
b/Misc/NEWS.d/next/Core_and_Builtins/2026-10-04-20-04-55.gh-issue-158816.9ulhWb.rst
new file mode 100644
index 000000000000000..fd9997afb3e1d34
--- /dev/null
+++ 
b/Misc/NEWS.d/next/Core_and_Builtins/2026-10-04-20-04-55.gh-issue-158816.9ulhWb.rst
@@ -0,0 +1,3 @@
+Speed up deleting items from split dictionaries (for example the
+materialized ``__dict__`` of an instance with inline values) by skipping a
+redundant hash table probe.
diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index 13c9e2e4b395abd..168a5a4118f596c 100644
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -2938,9 +2938,6 @@ delitem_common(PyDictObject *mp, Py_hash_t hash, 
Py_ssize_t ix,
 
     PyObject *old_key;
 
-    Py_ssize_t hashpos = lookdict_index(mp->ma_keys, hash, ix);
-    assert(hashpos >= 0);
-
     STORE_USED(mp, mp->ma_used - 1);
     if (_PyDict_HasSplitTable(mp)) {
         assert(old_value == mp->ma_values->values[ix]);
@@ -2951,6 +2948,9 @@ delitem_common(PyDictObject *mp, Py_hash_t hash, 
Py_ssize_t ix,
         ASSERT_CONSISTENT(mp);
     }
     else {
+        Py_ssize_t hashpos = lookdict_index(mp->ma_keys, hash, ix);
+        assert(hashpos >= 0);
+
         FT_ATOMIC_STORE_UINT32_RELAXED(mp->ma_keys->dk_version, 0);
         dictkeys_set_index(mp->ma_keys, hashpos, DKIX_DUMMY);
         if (DK_IS_UNICODE(mp->ma_keys)) {

_______________________________________________
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]

Reply via email to