https://github.com/python/cpython/commit/556749c3e33f7787da149f75ca1702b80383bead
commit: 556749c3e33f7787da149f75ca1702b80383bead
branch: main
author: Dino Viehland <[email protected]>
committer: DinoV <[email protected]>
date: 2024-02-29T13:38:50-08:00
summary:

gh-112075: Avoid locking shared keys on every assignment (#116087)

files:
M Objects/dictobject.c

diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index 5016e255f70ef9..9b8fc4a958f7ad 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(

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]

Reply via email to