码迷,mamicode.com
首页 > 其他好文 > 详细

redis学习笔记(一): sds

时间:2017-10-28 23:53:35      阅读:198      评论:0      收藏:0      [点我收藏+]

标签:new   sds   分配   sign   内容   返回   空间   笔记   return   

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

标签:new   sds   分配   sign   内容   返回   空间   笔记   return   

原文地址:http://www.cnblogs.com/flypighhblog/p/7748186.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!