Redis源码阅读之sds

目录

按照网上别人的建议,从数据结构相关的代码看起,reids version:3.2.0-rc3,涉及:

文件 内容
`sds.h` 和 `sds.c` Redis 的动态字符串实现。
`adlist.h` 和 `adlist.c` Redis 的双端链表实现。
dict.h 和 dict.c Redis 的字典实现。
`server.h` 中的 `zskiplist` 结构和 `zskiplistNode` 结构, 以及 t_zset.c 中所有以 zsl 开头的函数,比如 zslCreate 、 zslInsert 、 zslDeleteNode ,等等。 Redis 的跳跃表实现。
hyperloglog.c 中的 hllhdr 结构, 以及所有以 hll 开头的函数。 Redis 的 HyperLogLog 实现。

其中sds部分简单的看了下,在C原有的字符串基础上做了封装,主要的好处有这么几点: 1. 二进制安全,sds中允许存在’\0’作为一个正常的char了。同时会自动在字符串末尾增加一个’\0’,这样也就能支持部分c原有的一些函数 2. sds中保存了string的长度、free,当长度不足以保存的时候,自动进行扩容。这样就避免了溢出的风险,同时也不用频繁的分配内存 3. 根据字符串长度,定义了从TYPE5到TYPE64不同位长的类型来保存数据 #define SDS_HDR_VAR(T,s) struct sdshdr##T *sh = (void*)((s)-(sizeof(struct sdshdr##T))); 这段代码是什么鬼还没看懂……

struct __attribute__ ((__packed__)) sdshdr8 {
    uint8_t len; /* used */
    uint8_t alloc; /* excluding the header and null terminator */
    unsigned char flags; /* 3 lsb of type, 5 unused bits */
    char buf[];
};
struct __attribute__ ((__packed__)) sdshdr16 {
    uint16_t len; /* used */
    uint16_t alloc; /* excluding the header and null terminator */
    unsigned char flags; /* 3 lsb of type, 5 unused bits */
    char buf[];
};

根据字符串长度选择对应的类型保存len和alloc,对内存的使用果然是很抠门啊。