Skip to content

Commit 556749c

Browse files
authored
gh-112075: Avoid locking shared keys on every assignment (#116087)
1 parent 41d5391 commit 556749c

File tree

1 file changed

+20
-12
lines changed

1 file changed

+20
-12
lines changed

Objects/dictobject.c

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1597,19 +1597,11 @@ insertion_resize(PyInterpreterState *interp, PyDictObject *mp, int unicode)
15971597
}
15981598

15991599
static Py_ssize_t
1600-
insert_into_splitdictkeys(PyDictKeysObject *keys, PyObject *name)
1600+
insert_into_splitdictkeys(PyDictKeysObject *keys, PyObject *name, Py_hash_t hash)
16011601
{
16021602
assert(PyUnicode_CheckExact(name));
16031603
ASSERT_KEYS_LOCKED(keys);
16041604

1605-
Py_hash_t hash = unicode_get_hash(name);
1606-
if (hash == -1) {
1607-
hash = PyUnicode_Type.tp_hash(name);
1608-
if (hash == -1) {
1609-
PyErr_Clear();
1610-
return DKIX_EMPTY;
1611-
}
1612-
}
16131605
Py_ssize_t ix = unicodekeys_lookup_unicode(keys, name, hash);
16141606
if (ix == DKIX_EMPTY) {
16151607
if (keys->dk_usable <= 0) {
@@ -6692,8 +6684,25 @@ _PyObject_StoreInstanceAttribute(PyObject *obj, PyDictValues *values,
66926684
assert(Py_TYPE(obj)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
66936685
Py_ssize_t ix = DKIX_EMPTY;
66946686
if (PyUnicode_CheckExact(name)) {
6695-
LOCK_KEYS(keys);
6696-
ix = insert_into_splitdictkeys(keys, name);
6687+
Py_hash_t hash = unicode_get_hash(name);
6688+
if (hash == -1) {
6689+
hash = PyUnicode_Type.tp_hash(name);
6690+
assert(hash != -1);
6691+
}
6692+
6693+
#ifdef Py_GIL_DISABLED
6694+
// Try a thread-safe lookup to see if the index is already allocated
6695+
ix = unicodekeys_lookup_unicode_threadsafe(keys, name, hash);
6696+
if (ix == DKIX_EMPTY) {
6697+
// Lock keys and do insert
6698+
LOCK_KEYS(keys);
6699+
ix = insert_into_splitdictkeys(keys, name, hash);
6700+
UNLOCK_KEYS(keys);
6701+
}
6702+
#else
6703+
ix = insert_into_splitdictkeys(keys, name, hash);
6704+
#endif
6705+
66976706
#ifdef Py_STATS
66986707
if (ix == DKIX_EMPTY) {
66996708
if (PyUnicode_CheckExact(name)) {
@@ -6709,7 +6718,6 @@ _PyObject_StoreInstanceAttribute(PyObject *obj, PyDictValues *values,
67096718
}
67106719
}
67116720
#endif
6712-
UNLOCK_KEYS(keys);
67136721
}
67146722
if (ix == DKIX_EMPTY) {
67156723
PyObject *dict = make_dict_from_instance_attributes(

0 commit comments

Comments
 (0)