summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDino Viehland <dinoviehland@meta.com>2024-02-29 21:38:50 (GMT)
committerGitHub <noreply@github.com>2024-02-29 21:38:50 (GMT)
commit556749c3e33f7787da149f75ca1702b80383bead (patch)
treefdd3a59e82a6d340ece756662c8e18567c1cc667
parent41d5391c551e2012f13d56ff4bcc1df15c2821d3 (diff)
downloadcpython-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.c32
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(