[Zodb-checkins] CVS: Zope/lib/python/BTrees - SetOpTemplate.c:1.16
Tim Peters
tim.one@comcast.net
Fri, 31 May 2002 20:49:19 -0400
Update of /cvs-repository/Zope/lib/python/BTrees
In directory cvs.zope.org:/tmp/cvs-serv14639
Modified Files:
SetOpTemplate.c
Log Message:
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!).
=== Zope/lib/python/BTrees/SetOpTemplate.c 1.15 => 1.16 ===
set. At this point, we ignore the possibility of duplicates. */
for (i = 0; i < n; ++i) {
- SetIteration setiter = {0, 0, 0};
- int merge; /* dummy needed for initSetIteration */
-
set = PySequence_GetItem(seq, i);
if (set == NULL)
goto Error;
- /* XXX TODO: If set is a bucket, do a straight resize+memcpy instead.
- */
- if (initSetIteration(&setiter, set, 1, &merge) < 0)
- goto Error;
- if (setiter.next(&setiter) < 0)
- goto Error;
- while (setiter.position >= 0) {
- if (result->len >= result->size && Bucket_grow(result, -1, 1) < 0)
+ /* If set is a bucket, do a straight resize + memcpy. */
+ if (set->ob_type == (PyTypeObject*)&SetType ||
+ set->ob_type == (PyTypeObject*)&BucketType) {
+ const int setsize = SIZED(set)->len;
+ int size_desired = result->len + setsize;
+ /* If there are more to come, overallocate by 25% (arbitrary). */
+ if (i < n-1)
+ 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;
- 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;
+ 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);
set = NULL;