Skip to content

Commit

Permalink
Avoid locking shared keys on every assignment
Browse files Browse the repository at this point in the history
  • Loading branch information
DinoV committed Feb 29, 2024
1 parent 479ac5c commit af52498
Showing 1 changed file with 29 additions and 3 deletions.
32 changes: 29 additions & 3 deletions Objects/dictobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -1597,7 +1597,7 @@ insertion_resize(PyInterpreterState *interp, PyDictObject *mp, int unicode)
}

static Py_ssize_t
insert_into_splitdictkeys(PyDictKeysObject *keys, PyObject *name)
insert_into_splitdictkeys_locked(PyDictKeysObject *keys, PyObject *name)
{
assert(PyUnicode_CheckExact(name));
ASSERT_KEYS_LOCKED(keys);
Expand Down Expand Up @@ -1629,6 +1629,15 @@ insert_into_splitdictkeys(PyDictKeysObject *keys, PyObject *name)
return ix;
}

static int
insert_into_splitdictkeys(PyDictKeysObject *keys, PyObject *name)
{
LOCK_KEYS(keys);
Py_ssize_t ix = insert_into_splitdictkeys_locked(keys, name);
UNLOCK_KEYS(keys);
return ix;

Check warning on line 1638 in Objects/dictobject.c

View workflow job for this annotation

GitHub Actions / Windows (free-threading) / build and test (x64)

'return': conversion from 'Py_ssize_t' to 'int', possible loss of data [D:\a\cpython\cpython\PCbuild\pythoncore.vcxproj]

Check warning on line 1638 in Objects/dictobject.c

View workflow job for this annotation

GitHub Actions / Windows (free-threading) / build (arm64)

'return': conversion from 'Py_ssize_t' to 'int', possible loss of data [D:\a\cpython\cpython\PCbuild\pythoncore.vcxproj]

Check warning on line 1638 in Objects/dictobject.c

View workflow job for this annotation

GitHub Actions / Windows / build and test (x64)

'return': conversion from 'Py_ssize_t' to 'int', possible loss of data [D:\a\cpython\cpython\PCbuild\pythoncore.vcxproj]

Check warning on line 1638 in Objects/dictobject.c

View workflow job for this annotation

GitHub Actions / Windows / build (arm64)

'return': conversion from 'Py_ssize_t' to 'int', possible loss of data [D:\a\cpython\cpython\PCbuild\pythoncore.vcxproj]
}

static inline int
insert_combined_dict(PyInterpreterState *interp, PyDictObject *mp,
Py_hash_t hash, PyObject *key, PyObject *value)
Expand Down Expand Up @@ -6692,8 +6701,26 @@ _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);
#ifdef Py_GIL_DISABLED
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;
}
}

// 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) {
// Fall back to a version that will lock and maybe insert
ix = insert_into_splitdictkeys(keys, name);
}
#else
ix = insert_into_splitdictkeys(keys, name);
#endif

#ifdef Py_STATS
if (ix == DKIX_EMPTY) {
if (PyUnicode_CheckExact(name)) {
Expand All @@ -6709,7 +6736,6 @@ _PyObject_StoreInstanceAttribute(PyObject *obj, PyDictValues *values,
}
}
#endif
UNLOCK_KEYS(keys);
}
if (ix == DKIX_EMPTY) {
PyObject *dict = make_dict_from_instance_attributes(
Expand Down

0 comments on commit af52498

Please sign in to comment.