gh-112075: Avoid locking shared keys on every assignment (#116087) · python/cpython@556749c
@@ -1597,19 +1597,11 @@ insertion_resize(PyInterpreterState *interp, PyDictObject *mp, int unicode)
15971597}
1598159815991599static Py_ssize_t
1600-insert_into_splitdictkeys(PyDictKeysObject *keys, PyObject *name)
1600+insert_into_splitdictkeys(PyDictKeysObject *keys, PyObject *name, Py_hash_t hash)
16011601{
16021602assert(PyUnicode_CheckExact(name));
16031603ASSERT_KEYS_LOCKED(keys);
160416041605-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- }
16131605Py_ssize_t ix = unicodekeys_lookup_unicode(keys, name, hash);
16141606if (ix == DKIX_EMPTY) {
16151607if (keys->dk_usable <= 0) {
@@ -6692,8 +6684,25 @@ _PyObject_StoreInstanceAttribute(PyObject *obj, PyDictValues *values,
66926684assert(Py_TYPE(obj)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
66936685Py_ssize_t ix = DKIX_EMPTY;
66946686if (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
66986707if (ix == DKIX_EMPTY) {
66996708if (PyUnicode_CheckExact(name)) {
@@ -6709,7 +6718,6 @@ _PyObject_StoreInstanceAttribute(PyObject *obj, PyDictValues *values,
67096718 }
67106719 }
67116720#endif
6712-UNLOCK_KEYS(keys);
67136721 }
67146722if (ix == DKIX_EMPTY) {
67156723PyObject *dict = make_dict_from_instance_attributes(