Skip to content

Commit 86d48ef

Browse files
committed
Lazyfree: Convert Sets to use plains SDS (several commits squashed).
1 parent 4ff3c17 commit 86d48ef

File tree

9 files changed

+183
-163
lines changed

9 files changed

+183
-163
lines changed

src/db.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -415,8 +415,8 @@ void scanCallback(void *privdata, const dictEntry *de) {
415415
sds sdskey = dictGetKey(de);
416416
key = createStringObject(sdskey, sdslen(sdskey));
417417
} else if (o->type == OBJ_SET) {
418-
key = dictGetKey(de);
419-
incrRefCount(key);
418+
sds keysds = dictGetKey(de);
419+
key = createStringObject(keysds,sdslen(keysds));
420420
} else if (o->type == OBJ_HASH) {
421421
key = dictGetKey(de);
422422
incrRefCount(key);

src/debug.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,9 @@ void computeDatasetDigest(unsigned char *final) {
164164
} else if (o->type == OBJ_SET) {
165165
setTypeIterator *si = setTypeInitIterator(o);
166166
robj *ele;
167-
while((ele = setTypeNextObject(si)) != NULL) {
167+
sds sdsele;
168+
while((sdsele = setTypeNextObject(si)) != NULL) {
169+
ele = createObject(OBJ_STRING,sdsele);
168170
xorObjectDigest(digest,ele);
169171
decrRefCount(ele);
170172
}

src/networking.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,13 +117,13 @@ client *createClient(int fd) {
117117
listSetDupMethod(c->reply,dupClientReplyValue);
118118
c->btype = BLOCKED_NONE;
119119
c->bpop.timeout = 0;
120-
c->bpop.keys = dictCreate(&setDictType,NULL);
120+
c->bpop.keys = dictCreate(&objectKeyPointerValueDictType,NULL);
121121
c->bpop.target = NULL;
122122
c->bpop.numreplicas = 0;
123123
c->bpop.reploffset = 0;
124124
c->woff = 0;
125125
c->watched_keys = listCreate();
126-
c->pubsub_channels = dictCreate(&setDictType,NULL);
126+
c->pubsub_channels = dictCreate(&objectKeyPointerValueDictType,NULL);
127127
c->pubsub_patterns = listCreate();
128128
c->peerid = NULL;
129129
listSetFreeMethod(c->pubsub_patterns,decrRefCountVoid);

src/object.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -364,13 +364,17 @@ int checkType(client *c, robj *o, int type) {
364364
return 0;
365365
}
366366

367+
int isSdsRepresentableAsLongLong(sds s, long long *llval) {
368+
return string2ll(s,sdslen(s),llval) ? C_OK : C_ERR;
369+
}
370+
367371
int isObjectRepresentableAsLongLong(robj *o, long long *llval) {
368372
serverAssertWithInfo(NULL,o,o->type == OBJ_STRING);
369373
if (o->encoding == OBJ_ENCODING_INT) {
370374
if (llval) *llval = (long) o->ptr;
371375
return C_OK;
372376
} else {
373-
return string2ll(o->ptr,sdslen(o->ptr),llval) ? C_OK : C_ERR;
377+
return isSdsRepresentableAsLongLong(o->ptr,llval);
374378
}
375379
}
376380

src/rdb.c

Lines changed: 36 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
#define RDB_LOAD_NONE 0
4444
#define RDB_LOAD_ENC (1<<0)
4545
#define RDB_LOAD_PLAIN (1<<1)
46+
#define RDB_LOAD_SDS (1<<2)
4647

4748
#define rdbExitReportCorruptRDB(reason) rdbCheckThenExit(reason, __LINE__);
4849

@@ -179,6 +180,7 @@ int rdbEncodeInteger(long long value, unsigned char *enc) {
179180
* rdbGenerincLoadStringObject() for more info. */
180181
void *rdbLoadIntegerObject(rio *rdb, int enctype, int flags) {
181182
int plain = flags & RDB_LOAD_PLAIN;
183+
int sds = flags & RDB_LOAD_SDS;
182184
int encode = flags & RDB_LOAD_ENC;
183185
unsigned char enc[4];
184186
long long val;
@@ -200,10 +202,10 @@ void *rdbLoadIntegerObject(rio *rdb, int enctype, int flags) {
200202
val = 0; /* anti-warning */
201203
rdbExitReportCorruptRDB("Unknown RDB integer encoding type");
202204
}
203-
if (plain) {
205+
if (plain || sds) {
204206
char buf[LONG_STR_SIZE], *p;
205207
int len = ll2string(buf,sizeof(buf),val);
206-
p = zmalloc(len);
208+
p = plain ? zmalloc(len) : sdsnewlen(NULL,len);
207209
memcpy(p,buf,len);
208210
return p;
209211
} else if (encode) {
@@ -280,9 +282,10 @@ ssize_t rdbSaveLzfStringObject(rio *rdb, unsigned char *s, size_t len) {
280282
* rdbGenericLoadStringObject() function. */
281283
void *rdbLoadLzfStringObject(rio *rdb, int flags) {
282284
int plain = flags & RDB_LOAD_PLAIN;
285+
int sds = flags & RDB_LOAD_SDS;
283286
unsigned int len, clen;
284287
unsigned char *c = NULL;
285-
sds val = NULL;
288+
char *val = NULL;
286289

287290
if ((clen = rdbLoadLen(rdb,NULL)) == RDB_LENERR) return NULL;
288291
if ((len = rdbLoadLen(rdb,NULL)) == RDB_LENERR) return NULL;
@@ -292,18 +295,19 @@ void *rdbLoadLzfStringObject(rio *rdb, int flags) {
292295
if (plain) {
293296
val = zmalloc(len);
294297
} else {
295-
if ((val = sdsnewlen(NULL,len)) == NULL) goto err;
298+
val = sdsnewlen(NULL,len);
296299
}
297300

298301
/* Load the compressed representation and uncompress it to target. */
299302
if (rioRead(rdb,c,clen) == 0) goto err;
300303
if (lzf_decompress(c,clen,val,len) == 0) goto err;
301304
zfree(c);
302305

303-
if (plain)
306+
if (plain || sds) {
304307
return val;
305-
else
308+
} else {
306309
return createObject(OBJ_STRING,val);
310+
}
307311
err:
308312
zfree(c);
309313
if (plain)
@@ -366,7 +370,7 @@ ssize_t rdbSaveLongLongAsStringObject(rio *rdb, long long value) {
366370
return nwritten;
367371
}
368372

369-
/* Like rdbSaveStringObjectRaw() but handle encoded objects */
373+
/* Like rdbSaveRawString() gets a Redis object instead. */
370374
int rdbSaveStringObject(rio *rdb, robj *obj) {
371375
/* Avoid to decode the object, then encode it again, if the
372376
* object is already integer encoded. */
@@ -387,10 +391,12 @@ int rdbSaveStringObject(rio *rdb, robj *obj) {
387391
* no longer guarantees that obj->ptr is an SDS string.
388392
* RDB_LOAD_PLAIN: Return a plain string allocated with zmalloc()
389393
* instead of a Redis object.
394+
* RDB_LOAD_SDS: Return an SDS string instead of a Redis object.
390395
*/
391396
void *rdbGenericLoadStringObject(rio *rdb, int flags) {
392397
int encode = flags & RDB_LOAD_ENC;
393398
int plain = flags & RDB_LOAD_PLAIN;
399+
int sds = flags & RDB_LOAD_SDS;
394400
int isencoded;
395401
uint32_t len;
396402

@@ -409,21 +415,24 @@ void *rdbGenericLoadStringObject(rio *rdb, int flags) {
409415
}
410416

411417
if (len == RDB_LENERR) return NULL;
412-
if (!plain) {
418+
if (plain || sds) {
419+
void *buf = plain ? zmalloc(len) : sdsnewlen(NULL,len);
420+
if (len && rioRead(rdb,buf,len) == 0) {
421+
if (plain)
422+
zfree(buf);
423+
else
424+
sdsfree(buf);
425+
return NULL;
426+
}
427+
return buf;
428+
} else {
413429
robj *o = encode ? createStringObject(NULL,len) :
414430
createRawStringObject(NULL,len);
415431
if (len && rioRead(rdb,o->ptr,len) == 0) {
416432
decrRefCount(o);
417433
return NULL;
418434
}
419435
return o;
420-
} else {
421-
void *buf = zmalloc(len);
422-
if (len && rioRead(rdb,buf,len) == 0) {
423-
zfree(buf);
424-
return NULL;
425-
}
426-
return buf;
427436
}
428437
}
429438

@@ -583,8 +592,9 @@ ssize_t rdbSaveObject(rio *rdb, robj *o) {
583592
nwritten += n;
584593

585594
while((de = dictNext(di)) != NULL) {
586-
robj *eleobj = dictGetKey(de);
587-
if ((n = rdbSaveStringObject(rdb,eleobj)) == -1) return -1;
595+
sds ele = dictGetKey(de);
596+
if ((n = rdbSaveRawString(rdb,(unsigned char*)ele,sdslen(ele)))
597+
== -1) return -1;
588598
nwritten += n;
589599
}
590600
dictReleaseIterator(di);
@@ -959,7 +969,7 @@ robj *rdbLoadObject(int rdbtype, rio *rdb) {
959969
decrRefCount(ele);
960970
}
961971
} else if (rdbtype == RDB_TYPE_SET) {
962-
/* Read list/set value */
972+
/* Read Set value */
963973
if ((len = rdbLoadLen(rdb,NULL)) == RDB_LENERR) return NULL;
964974

965975
/* Use a regular set when there are too many entries. */
@@ -973,15 +983,17 @@ robj *rdbLoadObject(int rdbtype, rio *rdb) {
973983
o = createIntsetObject();
974984
}
975985

976-
/* Load every single element of the list/set */
986+
/* Load every single element of the set */
977987
for (i = 0; i < len; i++) {
978988
long long llval;
979-
if ((ele = rdbLoadEncodedStringObject(rdb)) == NULL) return NULL;
980-
ele = tryObjectEncoding(ele);
989+
sds sdsele;
990+
991+
if ((sdsele = rdbGenericLoadStringObject(rdb,RDB_LOAD_SDS)) == NULL)
992+
return NULL;
981993

982994
if (o->encoding == OBJ_ENCODING_INTSET) {
983995
/* Fetch integer value from element */
984-
if (isObjectRepresentableAsLongLong(ele,&llval) == C_OK) {
996+
if (isSdsRepresentableAsLongLong(sdsele,&llval) == C_OK) {
985997
o->ptr = intsetAdd(o->ptr,llval,NULL);
986998
} else {
987999
setTypeConvert(o,OBJ_ENCODING_HT);
@@ -992,9 +1004,9 @@ robj *rdbLoadObject(int rdbtype, rio *rdb) {
9921004
/* This will also be called when the set was just converted
9931005
* to a regular hash table encoded set */
9941006
if (o->encoding == OBJ_ENCODING_HT) {
995-
dictAdd((dict*)o->ptr,ele,NULL);
1007+
dictAdd((dict*)o->ptr,sdsele,NULL);
9961008
} else {
997-
decrRefCount(ele);
1009+
sdsfree(sdsele);
9981010
}
9991011
}
10001012
} else if (rdbtype == RDB_TYPE_ZSET) {

src/server.c

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -531,8 +531,9 @@ unsigned int dictEncObjHash(const void *key) {
531531
}
532532
}
533533

534-
/* Sets type hash table */
535-
dictType setDictType = {
534+
/* Generic hash table type where keys are Redis Objects, Values
535+
* dummy pointers. */
536+
dictType objectKeyPointerValueDictType = {
536537
dictEncObjHash, /* hash function */
537538
NULL, /* key dup */
538539
NULL, /* val dup */
@@ -541,13 +542,23 @@ dictType setDictType = {
541542
NULL /* val destructor */
542543
};
543544

545+
/* Set dictionary type. Keys are SDS strings, values are ot used. */
546+
dictType setDictType = {
547+
dictSdsHash, /* hash function */
548+
NULL, /* key dup */
549+
NULL, /* val dup */
550+
dictSdsKeyCompare, /* key compare */
551+
dictSdsDestructor, /* key destructor */
552+
NULL /* val destructor */
553+
};
554+
544555
/* Sorted sets hash (note: a skiplist is used in addition to the hash table) */
545556
dictType zsetDictType = {
546557
dictEncObjHash, /* hash function */
547558
NULL, /* key dup */
548559
NULL, /* val dup */
549560
dictEncObjKeyCompare, /* key compare */
550-
dictObjectDestructor, /* key destructor */
561+
dictObjectDestructor, /* key destructor */
551562
NULL /* val destructor */
552563
};
553564

@@ -1834,7 +1845,7 @@ void initServer(void) {
18341845
server.db[j].dict = dictCreate(&dbDictType,NULL);
18351846
server.db[j].expires = dictCreate(&keyptrDictType,NULL);
18361847
server.db[j].blocking_keys = dictCreate(&keylistDictType,NULL);
1837-
server.db[j].ready_keys = dictCreate(&setDictType,NULL);
1848+
server.db[j].ready_keys = dictCreate(&objectKeyPointerValueDictType,NULL);
18381849
server.db[j].watched_keys = dictCreate(&keylistDictType,NULL);
18391850
server.db[j].eviction_pool = evictionPoolAlloc();
18401851
server.db[j].id = j;

src/server.h

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1043,6 +1043,7 @@ typedef struct {
10431043

10441044
extern struct redisServer server;
10451045
extern struct sharedObjectsStruct shared;
1046+
extern dictType objectKeyPointerValueDictType;
10461047
extern dictType setDictType;
10471048
extern dictType zsetDictType;
10481049
extern dictType clusterNodesDictType;
@@ -1173,6 +1174,7 @@ robj *createStringObject(const char *ptr, size_t len);
11731174
robj *createRawStringObject(const char *ptr, size_t len);
11741175
robj *createEmbeddedStringObject(const char *ptr, size_t len);
11751176
robj *dupStringObject(robj *o);
1177+
int isSdsRepresentableAsLongLong(sds s, long long *llval);
11761178
int isObjectRepresentableAsLongLong(robj *o, long long *llongval);
11771179
robj *tryObjectEncoding(robj *o);
11781180
robj *getDecodedObject(robj *o);
@@ -1313,15 +1315,15 @@ unsigned int getLRUClock(void);
13131315
const char *maxmemoryToString(void);
13141316

13151317
/* Set data type */
1316-
robj *setTypeCreate(robj *value);
1317-
int setTypeAdd(robj *subject, robj *value);
1318-
int setTypeRemove(robj *subject, robj *value);
1319-
int setTypeIsMember(robj *subject, robj *value);
1318+
robj *setTypeCreate(sds value);
1319+
int setTypeAdd(robj *subject, sds value);
1320+
int setTypeRemove(robj *subject, sds value);
1321+
int setTypeIsMember(robj *subject, sds value);
13201322
setTypeIterator *setTypeInitIterator(robj *subject);
13211323
void setTypeReleaseIterator(setTypeIterator *si);
1322-
int setTypeNext(setTypeIterator *si, robj **objele, int64_t *llele);
1323-
robj *setTypeNextObject(setTypeIterator *si);
1324-
int setTypeRandomElement(robj *setobj, robj **objele, int64_t *llele);
1324+
int setTypeNext(setTypeIterator *si, sds *sdsele, int64_t *llele);
1325+
sds setTypeNextObject(setTypeIterator *si);
1326+
int setTypeRandomElement(robj *setobj, sds *sdsele, int64_t *llele);
13251327
unsigned long setTypeRandomElements(robj *set, unsigned long count, robj *aux_set);
13261328
unsigned long setTypeSize(robj *subject);
13271329
void setTypeConvert(robj *subject, int enc);

src/sort.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -380,9 +380,9 @@ void sortCommand(client *c) {
380380
listTypeReleaseIterator(li);
381381
} else if (sortval->type == OBJ_SET) {
382382
setTypeIterator *si = setTypeInitIterator(sortval);
383-
robj *ele;
384-
while((ele = setTypeNextObject(si)) != NULL) {
385-
vector[j].obj = ele;
383+
sds sdsele;
384+
while((sdsele = setTypeNextObject(si)) != NULL) {
385+
vector[j].obj = createObject(OBJ_STRING,sdsele);
386386
vector[j].u.score = 0;
387387
vector[j].u.cmpobj = NULL;
388388
j++;

0 commit comments

Comments
 (0)