diff options
author | Dino Viehland <dinoviehland@meta.com> | 2024-02-29 21:38:50 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-02-29 21:38:50 (GMT) |
commit | 556749c3e33f7787da149f75ca1702b80383bead (patch) | |
tree | fdd3a59e82a6d340ece756662c8e18567c1cc667 | |
parent | 41d5391c551e2012f13d56ff4bcc1df15c2821d3 (diff) | |
download | cpython-556749c3e33f7787da149f75ca1702b80383bead.zip cpython-556749c3e33f7787da149f75ca1702b80383bead.tar.gz cpython-556749c3e33f7787da149f75ca1702b80383bead.tar.bz2 |
gh-112075: Avoid locking shared keys on every assignment (#116087)
-rw-r--r-- | Objects/dictobject.c | 32 |
1 files changed, 20 insertions, 12 deletions
diff --git a/Objects/dictobject.c b/Objects/dictobject.c index 5016e25..9b8fc4a 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -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) { @@ -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)) { @@ -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( |