summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOran Agra <oran@redislabs.com>2022-06-14 21:12:45 +0300
committerGitHub <noreply@github.com>2022-06-14 21:12:45 +0300
commit2189100383ca06f8c8f163b340a265d018d9ebe9 (patch)
tree66222f6fa53851985d342b85411f5fa5a96ce468
parent8ef4f1dbad3c40dc90920c4aaa8a2f9f72637786 (diff)
downloadredis-2189100383ca06f8c8f163b340a265d018d9ebe9.tar.gz
optimize zset conversion on large ZRANGESTORE (#10789)
when we know the size of the zset we're gonna store in advance, we can check if it's greater than the listpack encoding threshold, in which case we can create a skiplist from the get go, and avoid converting the listpack to skiplist later after it was already populated.
-rw-r--r--src/t_zset.c6
-rw-r--r--tests/unit/type/zset.tcl14
2 files changed, 17 insertions, 3 deletions
diff --git a/src/t_zset.c b/src/t_zset.c
index 771d953b5..34f8fb74b 100644
--- a/src/t_zset.c
+++ b/src/t_zset.c
@@ -2952,8 +2952,10 @@ static void zrangeResultFinalizeClient(zrange_result_handler *handler,
/* Result handler methods for storing the ZRANGESTORE to a zset. */
static void zrangeResultBeginStore(zrange_result_handler *handler, long length)
{
- UNUSED(length);
- handler->dstobj = createZsetListpackObject();
+ if (length > (long)server.zset_max_listpack_entries)
+ handler->dstobj = createZsetObject();
+ else
+ handler->dstobj = createZsetListpackObject();
}
static void zrangeResultEmitCBufferForStore(zrange_result_handler *handler,
diff --git a/tests/unit/type/zset.tcl b/tests/unit/type/zset.tcl
index 4394117af..0e2457516 100644
--- a/tests/unit/type/zset.tcl
+++ b/tests/unit/type/zset.tcl
@@ -2208,7 +2208,7 @@ start_server {tags {"zset"}} {
assert_match "*syntax*" $err
}
- test {ZRANGESTORE with zset-max-listpack-entries 0 dst key should use skiplist encoding} {
+ test {ZRANGESTORE with zset-max-listpack-entries 0 #10767 case} {
set original_max [lindex [r config get zset-max-listpack-entries] 1]
r config set zset-max-listpack-entries 0
r del z1{t} z2{t}
@@ -2217,6 +2217,18 @@ start_server {tags {"zset"}} {
r config set zset-max-listpack-entries $original_max
}
+ test {ZRANGESTORE with zset-max-listpack-entries 1 dst key should use skiplist encoding} {
+ set original_max [lindex [r config get zset-max-listpack-entries] 1]
+ r config set zset-max-listpack-entries 1
+ r del z1{t} z2{t} z3{t}
+ r zadd z1{t} 1 a 2 b
+ assert_equal 1 [r zrangestore z2{t} z1{t} 0 0]
+ assert_encoding listpack z2{t}
+ assert_equal 2 [r zrangestore z3{t} z1{t} 0 1]
+ assert_encoding skiplist z3{t}
+ r config set zset-max-listpack-entries $original_max
+ }
+
test {ZRANGE invalid syntax} {
catch {r zrange z1{t} 0 -1 limit 1 2} err
assert_match "*syntax*" $err