redis学习笔记: sds

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了redis学习笔记: sds相关的知识,希望对你有一定的参考价值。

sds(Simple Dynamic String): 它其实就是普通的字符串,只是在每个字符串的前面加了一个管理用的头部,相关类型结构的定义如下

typedef char *sds;

struct sdshdr {
unsigned int len;   /* buf里面字符串的长度的 */
unsigned int free; /* buf里面剩余空间的大小,不算‘\0‘ */
char buf[];
};

它使用了零长数组,所以头部跟实际的内容是在一块连续的空间上,因此对外只需要返回buf的地址(也是sds),对内由sds的地址就能找到sdshdr(sds减8个字节)

相应地,sds内部实现了一些基本的操作,与c库最大的区别可能是sds的copy操作使用的是二进制(带长度的)操作。

sds内部分配新内存的原则是:

如果fee大于新增的长度,则不用新分配。

如果新的长度小于1M,则按新长度的2倍加sdshdr再1个字节来分配;

否则,分配的空间比新长度大1M加sdshdr再1个字节。

例如:一个sds存储"foo",那么其sdshdr={3,0,"foo"}。现在需要在其后面拼接" bar"四个字符。由于free是0,所以需要新的空间。由于3+4=7 < 1M,所以zrealloc时会指定长度为8 + 14 + 1。

zrealloc之后,sdshdr={7,7,"foo bar"}。只是,zrealloc之后,sdshdr本身的地址可能会变化?

具体可见函数sdsMakeRoomFor

sds sdsMakeRoomFor(sds s, size_t addlen) {
struct sdshdr *sh, *newsh;
size_t free = sdsavail(s);
size_t len, newlen;

if (free >= addlen) return s;
len = sdslen(s);
sh = (void*) (s-(sizeof(struct sdshdr)));
newlen = (len+addlen);
if (newlen < SDS_MAX_PREALLOC)
newlen *= 2;
else
newlen += SDS_MAX_PREALLOC;
newsh = zrealloc(sh, sizeof(struct sdshdr)+newlen+1);
if (newsh == NULL) return NULL;

newsh->free = newlen - len;
return newsh->buf;
}



















以上是关于redis学习笔记: sds的主要内容,如果未能解决你的问题,请参考以下文章

Redis学习笔记----简单动态字符串

《Redis设计与实现》学习笔记

学习笔记《Redis设计与实现》笔记

学习笔记《Redis设计与实现》笔记

redis学习笔记: dict

Redis学习笔记之底层数据结构