summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorRaymond Hettinger <rhettinger@users.noreply.github.com>2019-08-29 16:02:58 (GMT)
committerGitHub <noreply@github.com>2019-08-29 16:02:58 (GMT)
commit88ea166dadb8aeb34541a0a464662dea222629e5 (patch)
treeb9645a7bc80d97fb831ad252d467ff649f29b435 /Objects
parent4901fe274bc82b95dc89bcb3de8802a3dfedab32 (diff)
downloadcpython-88ea166dadb8aeb34541a0a464662dea222629e5.zip
cpython-88ea166dadb8aeb34541a0a464662dea222629e5.tar.gz
cpython-88ea166dadb8aeb34541a0a464662dea222629e5.tar.bz2
bpo-8425: Fast path for set inplace difference when the second set is large (GH-15590)
Diffstat (limited to 'Objects')
-rw-r--r--Objects/setobject.c18
1 files changed, 17 insertions, 1 deletions
diff --git a/Objects/setobject.c b/Objects/setobject.c
index 56858db..fafc2fa 100644
--- a/Objects/setobject.c
+++ b/Objects/setobject.c
@@ -1463,9 +1463,25 @@ set_difference_update_internal(PySetObject *so, PyObject *other)
setentry *entry;
Py_ssize_t pos = 0;
+ /* Optimization: When the other set is more than 8 times
+ larger than the base set, replace the other set with
+ interesection of the two sets.
+ */
+ if ((PySet_GET_SIZE(other) >> 3) > PySet_GET_SIZE(so)) {
+ other = set_intersection(so, other);
+ if (other == NULL)
+ return -1;
+ } else {
+ Py_INCREF(other);
+ }
+
while (set_next((PySetObject *)other, &pos, &entry))
- if (set_discard_entry(so, entry->key, entry->hash) < 0)
+ if (set_discard_entry(so, entry->key, entry->hash) < 0) {
+ Py_DECREF(other);
return -1;
+ }
+
+ Py_DECREF(other);
} else {
PyObject *key, *it;
it = PyObject_GetIter(other);