redis source code analysis (2) - SDS API details

In the source code analysis section, I try to use the native redis source code instead of looking at Huang Jianhong's comments to improve my ability to read the source code. In addition, the redis version is still 3.0
Source code download, you can go here


typedef char *sds;

sds sdsnewlen(const void *init, size_t initlen) {
    struct sdshdr *sh;

    //Allocate memory
    if (init) {
        sh = zmalloc(sizeof(struct sdshdr)+initlen+1);
    } else {
        sh = zcalloc(sizeof(struct sdshdr)+initlen+1);
    //NULL returned for allocation failure
    if (sh == NULL) return NULL;

    sh->len = initlen;
    sh->free = 0;//It can be seen here that sds initially does not allocate extra space.

    if (initlen && init)
        //If there is content in init, copy it.
        memcpy(sh->buf, init, initlen);
    sh->buf[initlen] = '\0';
    return (char*)sh->buf;

Here, two functions zmalloc and zcalloc are useful. The specific analysis is not covered in detail. The main difference between zmalloc and malloc is that zmalloc allocates more space than malloc (depending on the platform), which is used to store the size that zmalloc is supposed to allocate. The difference between zcalloc and zmalloc is that zmalloc does not initialize memory, but zcalloc does.


Create and return an sds that only holds the empty string ''.
sds sdsempty(void) {
return sdsnewlen("",0);


Convert a given c string to sds.

sds sdsnew(const char *init) {
    size_t initlen = (init == NULL) ? 0 : strlen(init);
    return sdsnewlen(init, initlen);


Copy sds

sds sdsdup(const sds s) {
    return sdsnewlen(s, sdslen(s));


Release sds

void sdsfree(sds s) {
    if (s == NULL) return;
    zfree(s-sizeof(struct sdshdr));

Functions of zfree
Free up memory and modify the memory size used by redis.


? Abandoned function
According to the code, I guess it's to resize the sds

void sdsupdatelen(sds s) {
    struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));
    int reallen = strlen(s);
    sh->free += (sh->len-reallen);
    sh->len = reallen;


Change sds to an empty string without actually freeing the sds space.

void sdsclear(sds s) {

    // Take out sdshdr
    struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));

    sh->free += sh->len;
    sh->len = 0;
    sh->buf[0] = '\0';



It really frees up the extra space when the inert space is released

sds sdsRemoveFreeSpace(sds s) {
    struct sdshdr *sh;

    sh = (void*) (s-(sizeof(struct sdshdr)));

    // Reallocate the memory so that the buf is only long enough to hold the string contents
    // T = O(N)
    sh = zrealloc(sh, sizeof(struct sdshdr)+sh->len+1);

    // Free space is 0
    sh->free = 0;

    return sh->buf;


Get the space allocated by sds to save the string (len+free+'(len + free + '\ 0'')

size_t sdsAllocSize(sds s) {
    struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));

    return sizeof(*sh)+sh->len+sh->free+1;


void sdsIncrLen(sds s, int incr) {
    struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));

    // Make sure the sds space is enough
    assert(sh->free >= incr);

    // Update properties
    sh->len += incr;
    sh->free -= incr;

    // This assert can be ignored
    // Because the previous assert has ensured SH - > Free - incr > = 0
    assert(sh->free >= 0);

    // Place a new ending symbol
    s[sh->len] = '\0';

Keywords: Redis

Added by growler123 on Mon, 04 May 2020 08:17:02 +0300