summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorantirez <antirez@gmail.com>2015-01-07 11:08:41 +0100
committerantirez <antirez@gmail.com>2015-01-07 11:08:41 +0100
commitf50fa6db2f9c8002bc52000faa19b1e9a1173bcd (patch)
tree24c2b78b77e698a9e88e9e7a84c64146b3a64281
parentf56299023760603cb7cbf600e5487709e097964f (diff)
downloadredis-f50fa6db2f9c8002bc52000faa19b1e9a1173bcd.tar.gz
New RDB v7 opcode: RESIZEDB.
The new opcode is an hint about the size of the dataset (keys and number of expires) we are going to load for a given Redis database inside the RDB file. Since hash tables are resized accordingly ASAP, useless rehashing is avoided, speeding up load times significantly, in the order of ~ 20% or more for larger data sets. Related issue: #1719
-rw-r--r--src/rdb.c26
-rw-r--r--src/rdb.h1
2 files changed, 26 insertions, 1 deletions
diff --git a/src/rdb.c b/src/rdb.c
index 4c8a22826..3e41d4044 100644
--- a/src/rdb.c
+++ b/src/rdb.c
@@ -714,6 +714,21 @@ int rdbSaveRio(rio *rdb, int *error) {
if (rdbSaveType(rdb,REDIS_RDB_OPCODE_SELECTDB) == -1) goto werr;
if (rdbSaveLen(rdb,j) == -1) goto werr;
+ /* Write the RESIZE DB opcode. We trim the size to UINT32_MAX, which
+ * is currently the largest type we are able to represent in RDB sizes.
+ * However this does not limit the actual size of the DB to load since
+ * these sizes are just hints to resize the hash tables. */
+ uint32_t db_size, expires_size;
+ db_size = (dictSize(db->dict) <= UINT32_MAX) ?
+ dictSize(db->dict) :
+ UINT32_MAX;
+ expires_size = (dictSize(db->dict) <= UINT32_MAX) ?
+ dictSize(db->expires) :
+ UINT32_MAX;
+ if (rdbSaveType(rdb,REDIS_RDB_OPCODE_RESIZEDB) == -1) goto werr;
+ if (rdbSaveLen(rdb,db_size) == -1) goto werr;
+ if (rdbSaveLen(rdb,expires_size) == -1) goto werr;
+
/* Iterate this DB writing every entry */
while((de = dictNext(di)) != NULL) {
sds keystr = dictGetKey(de);
@@ -1226,7 +1241,7 @@ int rdbLoad(char *filename) {
if (type == REDIS_RDB_OPCODE_EOF)
break;
- /* Handle SELECT DB opcode as a special case */
+ /* Handle special opcodes: SELECTDB, RESIZEDB, AUX. */
if (type == REDIS_RDB_OPCODE_SELECTDB) {
if ((dbid = rdbLoadLen(&rdb,NULL)) == REDIS_RDB_LENERR)
goto eoferr;
@@ -1236,6 +1251,15 @@ int rdbLoad(char *filename) {
}
db = server.db+dbid;
continue;
+ } else if (type == REDIS_RDB_OPCODE_RESIZEDB) {
+ uint32_t db_size, expires_size;
+ if ((db_size = rdbLoadLen(&rdb,NULL)) == REDIS_RDB_LENERR)
+ goto eoferr;
+ if ((expires_size = rdbLoadLen(&rdb,NULL)) == REDIS_RDB_LENERR)
+ goto eoferr;
+ dictExpand(db->dict,db_size);
+ dictExpand(db->expires,expires_size);
+ continue;
}
/* Read key */
if ((key = rdbLoadStringObject(&rdb)) == NULL) goto eoferr;
diff --git a/src/rdb.h b/src/rdb.h
index 55b3d261c..99bb19abe 100644
--- a/src/rdb.h
+++ b/src/rdb.h
@@ -89,6 +89,7 @@
#define rdbIsObjectType(t) ((t >= 0 && t <= 4) || (t >= 9 && t <= 14))
/* Special RDB opcodes (saved/loaded with rdbSaveType/rdbLoadType). */
+#define REDIS_RDB_OPCODE_RESIZEDB 251
#define REDIS_RDB_OPCODE_EXPIRETIME_MS 252
#define REDIS_RDB_OPCODE_EXPIRETIME 253
#define REDIS_RDB_OPCODE_SELECTDB 254