Skip to content

Commit

Permalink
Optimize sds free
Browse files Browse the repository at this point in the history
Eliminates cache-miss on free of String. SdsHdrSize is retieved from
calculating %8 operation on sds pointer. Added padding in 2 Sds Headers
to have unique value of %8 operation.
  • Loading branch information
jschmieg committed Jul 6, 2020
1 parent 4062e26 commit 085d8d9
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 1 deletion.
8 changes: 7 additions & 1 deletion src/object.c
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,12 @@ robj *createModuleObject(moduleType *mt, void *value) {
return createObject(OBJ_MODULE,mv);
}

void freeStringObjectOptim(robj *o) {
if (o->encoding == OBJ_ENCODING_RAW) {
sdsfreeOptim(o->ptr);
}
}

void freeStringObject(robj *o) {
if (o->encoding == OBJ_ENCODING_RAW) {
sdsfree(o->ptr);
Expand Down Expand Up @@ -356,7 +362,7 @@ void incrRefCount(robj *o) {
static void _decrRefCount(robj *o, int on_dram) {
if (o->refcount == 1) {
switch(o->type) {
case OBJ_STRING: freeStringObject(o); break;
case OBJ_STRING: freeStringObjectOptim(o); break;
case OBJ_LIST: freeListObject(o); break;
case OBJ_SET: freeSetObject(o); break;
case OBJ_ZSET: freeZsetObject(o); break;
Expand Down
23 changes: 23 additions & 0 deletions src/sds.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,24 @@ static inline int sdsHdrSize(char type) {
return 0;
}

/* Returns size of sdsHdr by checking pointer alignment (expects 8 byte
* alignment). Optimizes retriving sdsHdr size by not refering to sds data */
static inline int sdsHdrSizeOptim(char* s) {
switch((uintptr_t)s&7) {
case SDS_MOD8(5):
return sizeof(struct sdshdr5);
case SDS_MOD8(8):
return sizeof(struct sdshdr8);
case SDS_MOD8(16):
return sizeof(struct sdshdr16);
case SDS_MOD8(32):
return sizeof(struct sdshdr32);
case SDS_MOD8(64):
return sizeof(struct sdshdr64);
}
return 0;
}

static inline char sdsReqType(size_t string_size) {
if (string_size < 1<<5)
return SDS_TYPE_5;
Expand Down Expand Up @@ -185,6 +203,11 @@ void sdsfree(sds s) {
s_free((char*)s-sdsHdrSize(s[-1]));
}

void sdsfreeOptim(sds s) {
if (s == NULL) return;
s_free((char*)s-sdsHdrSizeOptim(s));
}

/* Set the sds string length to the length as obtained with strlen(), so
* considering as content only up to the first null term character.
*
Expand Down
4 changes: 4 additions & 0 deletions src/sds.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,14 @@ struct __attribute__ ((__packed__)) sdshdr32 {
uint32_t len; /* used */
uint32_t alloc; /* excluding the header and null terminator */
unsigned char flags; /* 3 lsb of type, 5 unused bits */
char padding; /* Added to have unique value for %8 operation*/
char buf[];
};
struct __attribute__ ((__packed__)) sdshdr64 {
uint64_t len; /* used */
uint64_t alloc; /* excluding the header and null terminator */
unsigned char flags; /* 3 lsb of type, 5 unused bits */
char padding[3]; /* Added to have unique value for %8 operation */
char buf[];
};

Expand All @@ -83,6 +85,7 @@ struct __attribute__ ((__packed__)) sdshdr64 {
#define SDS_HDR_VAR(T,s) struct sdshdr##T *sh = (void*)((s)-(sizeof(struct sdshdr##T)));
#define SDS_HDR(T,s) ((struct sdshdr##T *)((s)-(sizeof(struct sdshdr##T))))
#define SDS_TYPE_5_LEN(f) ((f)>>SDS_TYPE_BITS)
#define SDS_MOD8(T) (sizeof(struct sdshdr##T)&7)

static inline size_t sdslen(const sds s) {
unsigned char flags = s[-1];
Expand Down Expand Up @@ -221,6 +224,7 @@ sds sdsempty(void);
sds sdsdramempty(void);
sds sdsdup(const sds s);
void sdsfree(sds s);
void sdsfreeOptim(sds s);
sds sdsgrowzero(sds s, size_t len);
sds sdscatlen(sds s, const void *t, size_t len);
sds sdscat(sds s, const char *t);
Expand Down
1 change: 1 addition & 0 deletions src/server.h
Original file line number Diff line number Diff line change
Expand Up @@ -1724,6 +1724,7 @@ void incrRefCount(robj *o);
robj *makeObjectShared(robj *o);
robj *resetRefCount(robj *obj);
void freeStringObject(robj *o);
void freeStringObjectOptim(robj *o);
void freeListObject(robj *o);
void freeSetObject(robj *o);
void freeZsetObject(robj *o);
Expand Down

0 comments on commit 085d8d9

Please sign in to comment.