Commit 1d88ddbc authored by Tim Peters's avatar Tim Peters

multiunion(): For an input that's IIBucket-based (IIBucket and IISet),

this now copies the keys into the work area in one gulp via memcpy,
instead of iterating over them one at a time.  Yields a nice speedup when
it applies (and it usually should apply!).
parent b90f4bda
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
Set operations Set operations
****************************************************************************/ ****************************************************************************/
#define SETOPTEMPLATE_C "$Id: SetOpTemplate.c,v 1.15 2002/05/31 14:58:29 tim_one Exp $\n" #define SETOPTEMPLATE_C "$Id: SetOpTemplate.c,v 1.16 2002/06/01 00:49:19 tim_one Exp $\n"
#ifdef INTSET_H #ifdef INTSET_H
static int static int
...@@ -433,27 +433,45 @@ multiunion_m(PyObject *ignored, PyObject *args) ...@@ -433,27 +433,45 @@ multiunion_m(PyObject *ignored, PyObject *args)
/* For each set in the input sequence, append its elements to the result /* For each set in the input sequence, append its elements to the result
set. At this point, we ignore the possibility of duplicates. */ set. At this point, we ignore the possibility of duplicates. */
for (i = 0; i < n; ++i) { for (i = 0; i < n; ++i) {
SetIteration setiter = {0, 0, 0};
int merge; /* dummy needed for initSetIteration */
set = PySequence_GetItem(seq, i); set = PySequence_GetItem(seq, i);
if (set == NULL) if (set == NULL)
goto Error; goto Error;
/* XXX TODO: If set is a bucket, do a straight resize+memcpy instead. /* If set is a bucket, do a straight resize + memcpy. */
*/ if (set->ob_type == (PyTypeObject*)&SetType ||
if (initSetIteration(&setiter, set, 1, &merge) < 0) set->ob_type == (PyTypeObject*)&BucketType) {
goto Error; const int setsize = SIZED(set)->len;
if (setiter.next(&setiter) < 0) int size_desired = result->len + setsize;
goto Error; /* If there are more to come, overallocate by 25% (arbitrary). */
while (setiter.position >= 0) { if (i < n-1)
if (result->len >= result->size && Bucket_grow(result, -1, 1) < 0) size_desired += size_desired >> 2;
if (size_desired && size_desired > result->size) {
if (Bucket_grow(result, size_desired, 1) < 0)
goto Error;
}
memcpy(result->keys + result->len,
BUCKET(set)->keys,
setsize * sizeof(KEY_TYPE));
result->len += setsize;
}
else {
/* No cheap way: iterate over set's elements one at a time. */
SetIteration setiter = {0, 0, 0};
int merge; /* dummy needed for initSetIteration */
if (initSetIteration(&setiter, set, 1, &merge) < 0)
goto Error; goto Error;
COPY_KEY(result->keys[result->len], setiter.key);
++result->len;
/* We know the key is an int, so no need to incref it. */
if (setiter.next(&setiter) < 0) if (setiter.next(&setiter) < 0)
goto Error; goto Error;
while (setiter.position >= 0) {
if (result->len >= result->size && Bucket_grow(result, -1, 1) < 0)
goto Error;
COPY_KEY(result->keys[result->len], setiter.key);
++result->len;
/* We know the key is an int, so no need to incref it. */
if (setiter.next(&setiter) < 0)
goto Error;
}
} }
Py_DECREF(set); Py_DECREF(set);
set = NULL; set = NULL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment