gh-112075: Avoid locking shared keys on every assignment by DinoV · Pull Request #116087 · python/cpython
Expand Up
@@ -1597,19 +1597,11 @@ insertion_resize(PyInterpreterState *interp, PyDictObject *mp, int unicode)
}
static Py_ssize_t insert_into_splitdictkeys(PyDictKeysObject *keys, PyObject *name) insert_into_splitdictkeys(PyDictKeysObject *keys, PyObject *name, Py_hash_t hash) { assert(PyUnicode_CheckExact(name)); ASSERT_KEYS_LOCKED(keys);
Py_hash_t hash = unicode_get_hash(name); if (hash == -1) { hash = PyUnicode_Type.tp_hash(name); if (hash == -1) { PyErr_Clear(); return DKIX_EMPTY; } } Py_ssize_t ix = unicodekeys_lookup_unicode(keys, name, hash); if (ix == DKIX_EMPTY) { if (keys->dk_usable <= 0) { Expand Down Expand Up @@ -6692,8 +6684,25 @@ _PyObject_StoreInstanceAttribute(PyObject *obj, PyDictValues *values, assert(Py_TYPE(obj)->tp_flags & Py_TPFLAGS_MANAGED_DICT); Py_ssize_t ix = DKIX_EMPTY; if (PyUnicode_CheckExact(name)) { LOCK_KEYS(keys); ix = insert_into_splitdictkeys(keys, name); Py_hash_t hash = unicode_get_hash(name); if (hash == -1) { hash = PyUnicode_Type.tp_hash(name); assert(hash != -1); }
#ifdef Py_GIL_DISABLED // Try a thread-safe lookup to see if the index is already allocated ix = unicodekeys_lookup_unicode_threadsafe(keys, name, hash); if (ix == DKIX_EMPTY) { // Lock keys and do insert LOCK_KEYS(keys); ix = insert_into_splitdictkeys(keys, name, hash); UNLOCK_KEYS(keys); } #else ix = insert_into_splitdictkeys(keys, name, hash); #endif
#ifdef Py_STATS if (ix == DKIX_EMPTY) { if (PyUnicode_CheckExact(name)) { Expand All @@ -6709,7 +6718,6 @@ _PyObject_StoreInstanceAttribute(PyObject *obj, PyDictValues *values, } } #endif UNLOCK_KEYS(keys); } if (ix == DKIX_EMPTY) { PyObject *dict = make_dict_from_instance_attributes( Expand Down
static Py_ssize_t insert_into_splitdictkeys(PyDictKeysObject *keys, PyObject *name) insert_into_splitdictkeys(PyDictKeysObject *keys, PyObject *name, Py_hash_t hash) { assert(PyUnicode_CheckExact(name)); ASSERT_KEYS_LOCKED(keys);
Py_hash_t hash = unicode_get_hash(name); if (hash == -1) { hash = PyUnicode_Type.tp_hash(name); if (hash == -1) { PyErr_Clear(); return DKIX_EMPTY; } } Py_ssize_t ix = unicodekeys_lookup_unicode(keys, name, hash); if (ix == DKIX_EMPTY) { if (keys->dk_usable <= 0) { Expand Down Expand Up @@ -6692,8 +6684,25 @@ _PyObject_StoreInstanceAttribute(PyObject *obj, PyDictValues *values, assert(Py_TYPE(obj)->tp_flags & Py_TPFLAGS_MANAGED_DICT); Py_ssize_t ix = DKIX_EMPTY; if (PyUnicode_CheckExact(name)) { LOCK_KEYS(keys); ix = insert_into_splitdictkeys(keys, name); Py_hash_t hash = unicode_get_hash(name); if (hash == -1) { hash = PyUnicode_Type.tp_hash(name); assert(hash != -1); }
#ifdef Py_GIL_DISABLED // Try a thread-safe lookup to see if the index is already allocated ix = unicodekeys_lookup_unicode_threadsafe(keys, name, hash); if (ix == DKIX_EMPTY) { // Lock keys and do insert LOCK_KEYS(keys); ix = insert_into_splitdictkeys(keys, name, hash); UNLOCK_KEYS(keys); } #else ix = insert_into_splitdictkeys(keys, name, hash); #endif
#ifdef Py_STATS if (ix == DKIX_EMPTY) { if (PyUnicode_CheckExact(name)) { Expand All @@ -6709,7 +6718,6 @@ _PyObject_StoreInstanceAttribute(PyObject *obj, PyDictValues *values, } } #endif UNLOCK_KEYS(keys); } if (ix == DKIX_EMPTY) { PyObject *dict = make_dict_from_instance_attributes( Expand Down