Skip to content

Commit ee77d72

Browse files
committed
gh-158816: Skip redundant hash table probe when deleting from split dicts
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%) clang still does not sink the call into the branch at -O3 -DNDEBUG, so this is not specific to the local -Og build. test_dict, test_dictviews and test_dictcomps pass.
1 parent 9d22a53 commit ee77d72

2 files changed

Lines changed: 6 additions & 3 deletions

File tree

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Speed up deleting items from split dictionaries (for example the
2+
materialized ``__dict__`` of an instance with inline values) by skipping a
3+
redundant hash table probe.

‎Objects/dictobject.c‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2938,9 +2938,6 @@ delitem_common(PyDictObject *mp, Py_hash_t hash, Py_ssize_t ix,
29382938

29392939
PyObject *old_key;
29402940

2941-
Py_ssize_t hashpos = lookdict_index(mp->ma_keys, hash, ix);
2942-
assert(hashpos >= 0);
2943-
29442941
STORE_USED(mp, mp->ma_used - 1);
29452942
if (_PyDict_HasSplitTable(mp)) {
29462943
assert(old_value == mp->ma_values->values[ix]);
@@ -2951,6 +2948,9 @@ delitem_common(PyDictObject *mp, Py_hash_t hash, Py_ssize_t ix,
29512948
ASSERT_CONSISTENT(mp);
29522949
}
29532950
else {
2951+
Py_ssize_t hashpos = lookdict_index(mp->ma_keys, hash, ix);
2952+
assert(hashpos >= 0);
2953+
29542954
FT_ATOMIC_STORE_UINT32_RELAXED(mp->ma_keys->dk_version, 0);
29552955
dictkeys_set_index(mp->ma_keys, hashpos, DKIX_DUMMY);
29562956
if (DK_IS_UNICODE(mp->ma_keys)) {

0 commit comments

Comments
 (0)