mirror of
https://github.com/python/cpython.git
synced 2026-02-22 15:10:47 +00:00
gh-141510: Optimize {frozen}dict.fromkeys for frozendict (gh-144915)
This commit is contained in:
parent
fa73fd473f
commit
d1b541b047
2 changed files with 58 additions and 7 deletions
|
|
@ -0,0 +1,2 @@
|
|||
Optimize :meth:`!frozendict.fromkeys` to avoid unnecessary thread-safety operations
|
||||
in frozendict cases. Patch by Donghee Na.
|
||||
|
|
@ -2671,10 +2671,8 @@ _PyDict_LoadBuiltinsFromGlobals(PyObject *globals)
|
|||
|
||||
/* Consumes references to key and value */
|
||||
static int
|
||||
setitem_take2_lock_held(PyDictObject *mp, PyObject *key, PyObject *value)
|
||||
anydict_setitem_take2(PyDictObject *mp, PyObject *key, PyObject *value)
|
||||
{
|
||||
ASSERT_DICT_LOCKED(mp);
|
||||
|
||||
assert(key);
|
||||
assert(value);
|
||||
assert(PyAnyDict_Check(mp));
|
||||
|
|
@ -2693,6 +2691,14 @@ setitem_take2_lock_held(PyDictObject *mp, PyObject *key, PyObject *value)
|
|||
return insertdict(mp, key, hash, value);
|
||||
}
|
||||
|
||||
/* Consumes references to key and value */
|
||||
static int
|
||||
setitem_take2_lock_held(PyDictObject *mp, PyObject *key, PyObject *value)
|
||||
{
|
||||
ASSERT_DICT_LOCKED(mp);
|
||||
return anydict_setitem_take2(mp, key, value);
|
||||
}
|
||||
|
||||
int
|
||||
_PyDict_SetItem_Take2(PyDictObject *mp, PyObject *key, PyObject *value)
|
||||
{
|
||||
|
|
@ -3284,8 +3290,8 @@ _PyDict_FromKeys(PyObject *cls, PyObject *iterable, PyObject *value)
|
|||
return NULL;
|
||||
|
||||
|
||||
if (PyAnyDict_CheckExact(d)) {
|
||||
if (PyAnyDict_CheckExact(iterable)) {
|
||||
if (PyDict_CheckExact(d)) {
|
||||
if (PyDict_CheckExact(iterable)) {
|
||||
PyDictObject *mp = (PyDictObject *)d;
|
||||
|
||||
Py_BEGIN_CRITICAL_SECTION2(d, iterable);
|
||||
|
|
@ -3293,6 +3299,14 @@ _PyDict_FromKeys(PyObject *cls, PyObject *iterable, PyObject *value)
|
|||
Py_END_CRITICAL_SECTION2();
|
||||
return d;
|
||||
}
|
||||
else if (PyFrozenDict_CheckExact(iterable)) {
|
||||
PyDictObject *mp = (PyDictObject *)d;
|
||||
|
||||
Py_BEGIN_CRITICAL_SECTION(d);
|
||||
d = (PyObject *)dict_dict_fromkeys(mp, iterable, value);
|
||||
Py_END_CRITICAL_SECTION();
|
||||
return d;
|
||||
}
|
||||
else if (PyAnySet_CheckExact(iterable)) {
|
||||
PyDictObject *mp = (PyDictObject *)d;
|
||||
|
||||
|
|
@ -3302,6 +3316,29 @@ _PyDict_FromKeys(PyObject *cls, PyObject *iterable, PyObject *value)
|
|||
return d;
|
||||
}
|
||||
}
|
||||
else if (PyFrozenDict_CheckExact(d)) {
|
||||
if (PyDict_CheckExact(iterable)) {
|
||||
PyDictObject *mp = (PyDictObject *)d;
|
||||
|
||||
Py_BEGIN_CRITICAL_SECTION(iterable);
|
||||
d = (PyObject *)dict_dict_fromkeys(mp, iterable, value);
|
||||
Py_END_CRITICAL_SECTION();
|
||||
return d;
|
||||
}
|
||||
else if (PyFrozenDict_CheckExact(iterable)) {
|
||||
PyDictObject *mp = (PyDictObject *)d;
|
||||
d = (PyObject *)dict_dict_fromkeys(mp, iterable, value);
|
||||
return d;
|
||||
}
|
||||
else if (PyAnySet_CheckExact(iterable)) {
|
||||
PyDictObject *mp = (PyDictObject *)d;
|
||||
|
||||
Py_BEGIN_CRITICAL_SECTION(iterable);
|
||||
d = (PyObject *)dict_set_fromkeys(mp, iterable, value);
|
||||
Py_END_CRITICAL_SECTION();
|
||||
return d;
|
||||
}
|
||||
}
|
||||
|
||||
it = PyObject_GetIter(iterable);
|
||||
if (it == NULL){
|
||||
|
|
@ -3309,7 +3346,7 @@ _PyDict_FromKeys(PyObject *cls, PyObject *iterable, PyObject *value)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (PyAnyDict_CheckExact(d)) {
|
||||
if (PyDict_CheckExact(d)) {
|
||||
Py_BEGIN_CRITICAL_SECTION(d);
|
||||
while ((key = PyIter_Next(it)) != NULL) {
|
||||
status = setitem_lock_held((PyDictObject *)d, key, value);
|
||||
|
|
@ -3321,7 +3358,19 @@ _PyDict_FromKeys(PyObject *cls, PyObject *iterable, PyObject *value)
|
|||
}
|
||||
dict_iter_exit:;
|
||||
Py_END_CRITICAL_SECTION();
|
||||
} else {
|
||||
}
|
||||
else if (PyFrozenDict_CheckExact(d)) {
|
||||
while ((key = PyIter_Next(it)) != NULL) {
|
||||
// anydict_setitem_take2 consumes a reference to key
|
||||
status = anydict_setitem_take2((PyDictObject *)d,
|
||||
key, Py_NewRef(value));
|
||||
if (status < 0) {
|
||||
assert(PyErr_Occurred());
|
||||
goto Fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
while ((key = PyIter_Next(it)) != NULL) {
|
||||
status = PyObject_SetItem(d, key, value);
|
||||
Py_DECREF(key);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue