8000 Avoid locking shared keys on every assignment · python/cpython@22d7bfb · GitHub
[go: up one dir, main page]

Skip to content

Commit 22d7bfb

Browse files
committed
Avoid locking shared keys on every assignment
1 parent 479ac5c commit 22d7bfb

File tree

1 file changed

+29
-3
lines changed

1 file changed

+29
-3
lines changed

Objects/dictobject.c

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1597,7 +1597,7 @@ insertion_resize(PyInterpreterState *interp, PyDictObject *mp, int unicode)
15971597
}
15981598

15991599
static Py_ssize_t
1600-
insert_into_splitdictkeys(PyDictKeysObject *keys, PyObject *name)
1600+
insert_into_splitdictkeys_locked(PyDictKeysObject *keys, PyObject *name)
16011601
{
16021602
assert(PyUnicode_CheckExact(name));
16031603
ASSERT_KEYS_LOCKED(keys);
@@ -1629,6 +1629,15 @@ insert_into_splitdictkeys(PyDictKeysObject *keys, PyObject *name)
16291629
return ix;
16301630
}
16311631

1632+
static Py_ssize_t
1633+
insert_into_splitdictkeys(PyDictKeysObject *keys, PyObject *name)
1634+
{
1635+
LOCK_KEYS(keys);
1636+
Py_ssize_t ix = insert_into_splitdictkeys_locked(keys, name);
1637+
UNLOCK_KEYS(keys);
1638+
return ix;
1639+
}
1640+
16321641
static inline int
16331642
insert_combined_dict(PyInterpreterState *interp, PyDictObject *mp,
16341643
Py_hash_t hash, PyObject *key, PyObject *value)
@@ -6692,8 +6701,26 @@ _PyObject_StoreInstanceAttribute(PyObject *obj, PyDictValues *values,
66926701
assert(Py_TYPE(obj)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
66936702
Py_ssize_t ix = DKIX_EMPTY;
66946703
if (PyUnicode_CheckExact(name)) {
6695-
LOCK_KEYS(keys);
6704+
#ifdef Py_GIL_DISABLED
6705+
Py_hash_t hash = unicode_get_hash(name);
6706+
if (hash == -1) {
6707+
hash = PyUnicode_Type.tp_hash(name);
6708+
if (hash == -1) {
6709+
PyErr_Clear();
6710+
return DKIX_EMPTY;
6711+
}
6712+
}
6713+
6714+
// Try a thread-safe lookup to see if the index is already allocated
6715+
ix = unicodekeys_lookup_unicode_threadsafe(keys, name, hash);
6716+
if (ix == DKIX_EMPTY) {
6717+
// Fall back to a version that will lock and maybe insert
6718+
ix = insert_into_splitdictkeys(keys, name);
6719+
}
6720+
#else
66966721
ix = insert_into_splitdictkeys(keys, name);
6722+
#endif
6723+
66976724
#ifdef Py_STATS
66986725
if (ix == DKIX_EMPTY) {
66996726
if (PyUnicode_CheckExact(name)) {
@@ -6709,7 +6736,6 @@ _PyObject_StoreInstanceAttribute(PyObject *obj, PyDictValues *values,
67096736
}
67106737
}
67116738
#endif
6712-
UNLOCK_KEYS(keys);
67136739
}
67146740
if (ix == DKIX_EMPTY) {
67156741
PyObject *dict = make_dict_from_instance_attributes(

0 commit comments

Comments
 (0)
0