From 3ea204e1031a94dafca7f7e4eed2f79ec3bd7fd0 Mon Sep 17 00:00:00 2001
From: Pieter Noordhuis <pcnoordhuis@gmail.com>
Date: Wed, 9 Mar 2011 14:01:57 +0100
Subject: [PATCH] Configurable thresholds for encoded sorted sets

---
 redis.conf   |  6 ++++++
 src/config.c | 20 ++++++++++++++++++++
 src/redis.c  |  2 ++
 src/redis.h  |  4 ++++
 4 files changed, 32 insertions(+)

diff --git a/redis.conf b/redis.conf
index a470c98cf..e7a01eec4 100644
--- a/redis.conf
+++ b/redis.conf
@@ -340,6 +340,12 @@ list-max-ziplist-value 64
 # set in order to use this special memory saving encoding.
 set-max-intset-entries 512
 
+# Similarly to hashes and lists, sorted sets are also specially encoded in
+# order to save a lot of space. This encoding is only used when the length and
+# elements of a sorted set are below the following limits:
+zset-max-ziplist-entries 128
+zset-max-ziplist-value 64
+
 # Active rehashing uses 1 millisecond every 100 milliseconds of CPU time in
 # order to help rehashing the main Redis hash table (the one mapping top-level
 # keys to values). The hash table implementation redis uses (see dict.c)
diff --git a/src/config.c b/src/config.c
index e0bf1574a..fec72a45e 100644
--- a/src/config.c
+++ b/src/config.c
@@ -261,6 +261,10 @@ void loadServerConfig(char *filename) {
             server.list_max_ziplist_value = memtoll(argv[1], NULL);
         } else if (!strcasecmp(argv[0],"set-max-intset-entries") && argc == 2) {
             server.set_max_intset_entries = memtoll(argv[1], NULL);
+        } else if (!strcasecmp(argv[0],"zset-max-ziplist-entries") && argc == 2) {
+            server.zset_max_ziplist_entries = memtoll(argv[1], NULL);
+        } else if (!strcasecmp(argv[0],"zset-max-ziplist-value") && argc == 2) {
+            server.zset_max_ziplist_value = memtoll(argv[1], NULL);
         } else if (!strcasecmp(argv[0],"rename-command") && argc == 3) {
             struct redisCommand *cmd = lookupCommand(argv[1]);
             int retval;
@@ -443,6 +447,12 @@ void configSetCommand(redisClient *c) {
     } else if (!strcasecmp(c->argv[2]->ptr,"set-max-intset-entries")) {
         if (getLongLongFromObject(o,&ll) == REDIS_ERR || ll < 0) goto badfmt;
         server.set_max_intset_entries = ll;
+    } else if (!strcasecmp(c->argv[2]->ptr,"zset-max-ziplist-entries")) {
+        if (getLongLongFromObject(o,&ll) == REDIS_ERR || ll < 0) goto badfmt;
+        server.zset_max_ziplist_entries = ll;
+    } else if (!strcasecmp(c->argv[2]->ptr,"zset-max-ziplist-value")) {
+        if (getLongLongFromObject(o,&ll) == REDIS_ERR || ll < 0) goto badfmt;
+        server.zset_max_ziplist_value = ll;
     } else {
         addReplyErrorFormat(c,"Unsupported CONFIG parameter: %s",
             (char*)c->argv[2]->ptr);
@@ -594,6 +604,16 @@ void configGetCommand(redisClient *c) {
         addReplyBulkLongLong(c,server.set_max_intset_entries);
         matches++;
     }
+    if (stringmatch(pattern,"zset-max-ziplist-entries",0)) {
+        addReplyBulkCString(c,"zset-max-ziplist-entries");
+        addReplyBulkLongLong(c,server.zset_max_ziplist_entries);
+        matches++;
+    }
+    if (stringmatch(pattern,"zset-max-ziplist-value",0)) {
+        addReplyBulkCString(c,"zset-max-ziplist-value");
+        addReplyBulkLongLong(c,server.zset_max_ziplist_value);
+        matches++;
+    }
     setDeferredMultiBulkLength(c,replylen,matches*2);
 }
 
diff --git a/src/redis.c b/src/redis.c
index 866ac360a..2b98d40c5 100644
--- a/src/redis.c
+++ b/src/redis.c
@@ -821,6 +821,8 @@ void initServerConfig() {
     server.list_max_ziplist_entries = REDIS_LIST_MAX_ZIPLIST_ENTRIES;
     server.list_max_ziplist_value = REDIS_LIST_MAX_ZIPLIST_VALUE;
     server.set_max_intset_entries = REDIS_SET_MAX_INTSET_ENTRIES;
+    server.zset_max_ziplist_entries = REDIS_ZSET_MAX_ZIPLIST_ENTRIES;
+    server.zset_max_ziplist_value = REDIS_ZSET_MAX_ZIPLIST_VALUE;
     server.shutdown_asap = 0;
     server.cache_flush_delay = 0;
 
diff --git a/src/redis.h b/src/redis.h
index 9924cee72..9f53583e6 100644
--- a/src/redis.h
+++ b/src/redis.h
@@ -197,6 +197,8 @@
 #define REDIS_LIST_MAX_ZIPLIST_ENTRIES 512
 #define REDIS_LIST_MAX_ZIPLIST_VALUE 64
 #define REDIS_SET_MAX_INTSET_ENTRIES 512
+#define REDIS_ZSET_MAX_ZIPLIST_ENTRIES 128
+#define REDIS_ZSET_MAX_ZIPLIST_VALUE 64
 
 /* Sets operations codes */
 #define REDIS_OP_UNION 0
@@ -470,6 +472,8 @@ struct redisServer {
     size_t list_max_ziplist_entries;
     size_t list_max_ziplist_value;
     size_t set_max_intset_entries;
+    size_t zset_max_ziplist_entries;
+    size_t zset_max_ziplist_value;
     time_t unixtime;    /* Unix time sampled every second. */
     /* Virtual memory I/O threads stuff */
     /* An I/O thread process an element taken from the io_jobs queue and