Iterate backwards on zdiff/zinter/zunion to optimize for zslInsert (#8105)

In the iterator for these functions, we'll traverse the sorted sets
in a reversed way so that largest elements come first. We prefer
this order because it's optimized for insertion in a skiplist, which
is the destination of the elements being iterated in there functions.
This commit is contained in:
Felipe Machado 2020-12-03 05:12:07 -03:00 committed by GitHub
parent 7459652e3e
commit 4cd1fb1f40
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1965,17 +1965,20 @@ void zuiInitIterator(zsetopsrc *op) {
serverPanic("Unknown set encoding"); serverPanic("Unknown set encoding");
} }
} else if (op->type == OBJ_ZSET) { } else if (op->type == OBJ_ZSET) {
/* Sorted sets are traversed in reverse order to optimize for
* the insertion of the elements in a new list as in
* ZDIFF/ZINTER/ZUNION */
iterzset *it = &op->iter.zset; iterzset *it = &op->iter.zset;
if (op->encoding == OBJ_ENCODING_ZIPLIST) { if (op->encoding == OBJ_ENCODING_ZIPLIST) {
it->zl.zl = op->subject->ptr; it->zl.zl = op->subject->ptr;
it->zl.eptr = ziplistIndex(it->zl.zl,0); it->zl.eptr = ziplistIndex(it->zl.zl,-2);
if (it->zl.eptr != NULL) { if (it->zl.eptr != NULL) {
it->zl.sptr = ziplistNext(it->zl.zl,it->zl.eptr); it->zl.sptr = ziplistNext(it->zl.zl,it->zl.eptr);
serverAssert(it->zl.sptr != NULL); serverAssert(it->zl.sptr != NULL);
} }
} else if (op->encoding == OBJ_ENCODING_SKIPLIST) { } else if (op->encoding == OBJ_ENCODING_SKIPLIST) {
it->sl.zs = op->subject->ptr; it->sl.zs = op->subject->ptr;
it->sl.node = it->sl.zs->zsl->header->level[0].forward; it->sl.node = it->sl.zs->zsl->tail;
} else { } else {
serverPanic("Unknown sorted set encoding"); serverPanic("Unknown sorted set encoding");
} }
@ -2082,16 +2085,16 @@ int zuiNext(zsetopsrc *op, zsetopval *val) {
serverAssert(ziplistGet(it->zl.eptr,&val->estr,&val->elen,&val->ell)); serverAssert(ziplistGet(it->zl.eptr,&val->estr,&val->elen,&val->ell));
val->score = zzlGetScore(it->zl.sptr); val->score = zzlGetScore(it->zl.sptr);
/* Move to next element. */ /* Move to next element (going backwards, see zuiInitIterator). */
zzlNext(it->zl.zl,&it->zl.eptr,&it->zl.sptr); zzlPrev(it->zl.zl,&it->zl.eptr,&it->zl.sptr);
} else if (op->encoding == OBJ_ENCODING_SKIPLIST) { } else if (op->encoding == OBJ_ENCODING_SKIPLIST) {
if (it->sl.node == NULL) if (it->sl.node == NULL)
return 0; return 0;
val->ele = it->sl.node->ele; val->ele = it->sl.node->ele;
val->score = it->sl.node->score; val->score = it->sl.node->score;
/* Move to next element. */ /* Move to next element. (going backwards, see zuiInitIterator) */
it->sl.node = it->sl.node->level[0].forward; it->sl.node = it->sl.node->backward;
} else { } else {
serverPanic("Unknown sorted set encoding"); serverPanic("Unknown sorted set encoding");
} }