Skip to content

Commit

Permalink
Opt ZUNION[STORE] by removing redundant temporary dict
Browse files Browse the repository at this point in the history
  • Loading branch information
RayaCoo authored and moticless committed Sep 23, 2024
1 parent 5f28bd9 commit e506251
Showing 1 changed file with 11 additions and 47 deletions.
58 changes: 11 additions & 47 deletions src/t_zset.c
Original file line number Diff line number Diff line change
@@ -1,31 +1,12 @@
/*
* Copyright (c) 2009-current, Redis Ltd.
* Copyright (c) 2009-2012, Pieter Noordhuis <pcnoordhuis at gmail dot com>
* All rights reserved.
/* t_zset.c -- zset data type implementation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* Copyright (c) 2009-Present, Redis Ltd.
* All rights reserved.
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Redis nor the names of its contributors may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
* Licensed under your choice of the Redis Source Available License 2.0
* (RSALv2) or the Server Side Public License v1 (SSPLv1).
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* Portions of this file are available under BSD3 terms; see REDISCONTRIBUTIONS for more information.
*/

/*-----------------------------------------------------------------------------
Expand Down Expand Up @@ -2611,16 +2592,6 @@ static void zdiff(zsetopsrc *src, long setnum, zset *dstzset, size_t *maxelelen,
}
}

dictType setAccumulatorDictType = {
dictSdsHash, /* hash function */
NULL, /* key dup */
NULL, /* val dup */
dictSdsKeyCompare, /* key compare */
NULL, /* key destructor */
NULL, /* val destructor */
NULL /* allow to expand */
};

/* The zunionInterDiffGenericCommand() function is called in order to implement the
* following commands: ZUNION, ZINTER, ZDIFF, ZUNIONSTORE, ZINTERSTORE, ZDIFFSTORE,
* ZINTERCARD.
Expand Down Expand Up @@ -2816,15 +2787,14 @@ void zunionInterDiffGenericCommand(client *c, robj *dstkey, int numkeysIndex, in
zuiClearIterator(&src[0]);
}
} else if (op == SET_OP_UNION) {
dict *accumulator = dictCreate(&setAccumulatorDictType);
dictIterator *di;
dictEntry *de, *existing;
double score;

if (setnum) {
/* Our union is at least as large as the largest set.
* Resize the dictionary ASAP to avoid useless rehashing. */
dictExpand(accumulator,zuiLength(&src[setnum-1]));
dictExpand(dstzset->dict,zuiLength(&src[setnum-1]));
}

/* Step 1: Create a dictionary of elements -> aggregated-scores
Expand All @@ -2839,7 +2809,7 @@ void zunionInterDiffGenericCommand(client *c, robj *dstkey, int numkeysIndex, in
if (isnan(score)) score = 0;

/* Search for this element in the accumulating dictionary. */
de = dictAddRaw(accumulator,zuiSdsFromValue(&zval),&existing);
de = dictAddRaw(dstzset->dict,zuiSdsFromValue(&zval),&existing);
/* If we don't have it, we need to create a new entry. */
if (!existing) {
tmp = zuiNewSdsFromValue(&zval);
Expand All @@ -2849,7 +2819,7 @@ void zunionInterDiffGenericCommand(client *c, robj *dstkey, int numkeysIndex, in
totelelen += sdslen(tmp);
if (sdslen(tmp) > maxelelen) maxelelen = sdslen(tmp);
/* Update the element with its initial score. */
dictSetKey(accumulator, de, tmp);
dictSetKey(dstzset->dict, de, tmp);
dictSetDoubleVal(de,score);
} else {
/* Update the score with the score of the new instance
Expand All @@ -2866,21 +2836,15 @@ void zunionInterDiffGenericCommand(client *c, robj *dstkey, int numkeysIndex, in
}

/* Step 2: convert the dictionary into the final sorted set. */
di = dictGetIterator(accumulator);

/* We now are aware of the final size of the resulting sorted set,
* let's resize the dictionary embedded inside the sorted set to the
* right size, in order to save rehashing time. */
dictExpand(dstzset->dict,dictSize(accumulator));
di = dictGetIterator(dstzset->dict);

while((de = dictNext(di)) != NULL) {
sds ele = dictGetKey(de);
score = dictGetDoubleVal(de);
znode = zslInsert(dstzset->zsl,score,ele);
dictAdd(dstzset->dict,ele,&znode->score);
dictSetVal(dstzset->dict,de,&znode->score);
}
dictReleaseIterator(di);
dictRelease(accumulator);
} else if (op == SET_OP_DIFF) {
zdiff(src, setnum, dstzset, &maxelelen, &totelelen);
} else {
Expand Down

0 comments on commit e506251

Please sign in to comment.