bpo-38613: Optimize set operations of dict keys. (GH-16961)

This commit is contained in:
Inada Naoki 2019-11-08 00:59:04 +09:00 committed by GitHub
parent d12d0e7c0f
commit 6cbc84fb99
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 38 additions and 23 deletions

View File

@ -0,0 +1,3 @@
Optimized some set operations (e.g. ``|``, ``^``, and ``-``) of
``dict_keys``. ``d.keys() | other`` was slower than ``set(d) | other`` but
they are almost same performance for now.

View File

@ -4162,17 +4162,34 @@ static PySequenceMethods dictkeys_as_sequence = {
(objobjproc)dictkeys_contains, /* sq_contains */
};
// Create an set object from dictviews object.
// Returns a new reference.
// This utility function is used by set operations.
static PyObject*
dictviews_sub(PyObject* self, PyObject *other)
dictviews_to_set(PyObject *self)
{
PyObject *result = PySet_New(self);
PyObject *tmp;
_Py_IDENTIFIER(difference_update);
PyObject *left = self;
if (PyDictKeys_Check(self)) {
// PySet_New() has fast path for the dict object.
PyObject *dict = (PyObject *)((_PyDictViewObject *)self)->dv_dict;
if (PyDict_CheckExact(dict)) {
left = dict;
}
}
return PySet_New(left);
}
if (result == NULL)
static PyObject*
dictviews_sub(PyObject *self, PyObject *other)
{
PyObject *result = dictviews_to_set(self);
if (result == NULL) {
return NULL;
}
tmp = _PyObject_CallMethodIdOneArg(result, &PyId_difference_update, other);
_Py_IDENTIFIER(difference_update);
PyObject *tmp = _PyObject_CallMethodIdOneArg(
result, &PyId_difference_update, other);
if (tmp == NULL) {
Py_DECREF(result);
return NULL;
@ -4273,34 +4290,29 @@ error:
static PyObject*
dictviews_or(PyObject* self, PyObject *other)
{
PyObject *result = PySet_New(self);
PyObject *tmp;
_Py_IDENTIFIER(update);
if (result == NULL)
return NULL;
tmp = _PyObject_CallMethodIdOneArg(result, &PyId_update, other);
if (tmp == NULL) {
Py_DECREF(result);
PyObject *result = dictviews_to_set(self);
if (result == NULL) {
return NULL;
}
Py_DECREF(tmp);
if (_PySet_Update(result, other) < 0) {
Py_DECREF(result);
return NULL;
}
return result;
}
static PyObject*
dictviews_xor(PyObject* self, PyObject *other)
{
PyObject *result = PySet_New(self);
PyObject *tmp;
_Py_IDENTIFIER(symmetric_difference_update);
if (result == NULL)
PyObject *result = dictviews_to_set(self);
if (result == NULL) {
return NULL;
}
tmp = _PyObject_CallMethodIdOneArg(result, &PyId_symmetric_difference_update, other);
_Py_IDENTIFIER(symmetric_difference_update);
PyObject *tmp = _PyObject_CallMethodIdOneArg(
result, &PyId_symmetric_difference_update, other);
if (tmp == NULL) {
Py_DECREF(result);
return NULL;