Junhc

岂止于博客

Redis简单动态字符串

SDS的定义
struct sdshdr {
  // 记录buf数组中已使用字节的数量
  // 等于SDS所保存字符串的长度
  int len;

  // 记录buf数组中未使用字节的数量
  int free;

  // 字节数组, 用于保存字符串
  char buf[];
}

SDS遵循C语言传统的字符串以空字符结尾的惯例,保存空字符的1字节空间不计算在SDS的len属性里面,
并且为空字符串分配额外的1字节空间,以及添加空字符到字符串末尾等操作,都是有SDS函数自动完成的。

SDS与C语言字符串的区别
1. 常数复杂度获取字符串长度
2. 杜绝缓冲区溢出
3. 减少修改字符串时带来的内存重分配次数
3.1 空间预分配

如果对SDS进行修改之后,SDS的长度(也即是len属性的值)将小于1MB,
那么程序分配和len属性同样大小的未使用空间,这时SDS len属性的值将和free属性的值相同。
如果对SDS进行修改之后,SDS的长度大于等于1MB,那么程序会分配1MB未使用的空间。
通过空间预分配策略,Redis可以减少连续执行字符串增长操作所需的内存重分配次数。

3.2 惰性空间释放

当SDS的API需要缩短SDS保存的字符串时,程序并不立即使用内存重分配回收缩短后多出来的字节,
而使用free属性将这些字节的数量记录起来,并等待将来使用。

4. 二进制安全
5. 兼容部分C字符串函数