简单动态字符串SDS(Simple Dynamic String)
//SDS数据结构如下
struct sdshdr{
//len用来记录buf数组中已使用字节的数量
//等于SDS所保存字符串的长度
int len;
//记录buf数组中未使用字节的数量
int free;
//字节数组,用于保存字符串
char buf[];
}
基于SDS数据结构的定义和一些API规则,SDS相比于C字符串有如下优势
1. 获取字符串长度的复杂度为O(1),C字符串的复杂度为O(n)
2. 杜绝缓冲区溢出
3. 减少修改字符串时带来的内存重分配次数
4. 二进制安全
原理分析
- 由于结构体中len属性的存在,因此查询字符串长度,只需知道len的值是多少就可以了,而无需遍历整个字符串(C字符串就是这么做的,所以为O(n))。同时,SDS字符串结束不是通过空字符串\0来判断的,也是通过len属性来判断的,通过\0来判断字符串结束,会有诸多限制,如果字符串中本身包含\0,那么\0后面的字符就会丢失,所以SDS可以用来存储任何数据,而C字符串则不能保存图片、音频、视频等二进制数据。
- 由于Free属性的存在,以及空间预分配策略和惰性空间释放规则,可以减少内存空间重分配次数,这样会大大提升性能,C字符串内存空间是刚好用来存储字符串,但是当要缩小字符串长度时,如果不进行内存重分配,则会导致内存泄露,当要增加字符串长度时,如果不进行内存重分配,则会导致内存溢出,如果进行内存重分配,在频繁修改字符串长度的场景下,则会导致性能大幅度下降。
- SDS同时也会在最后一个位置放\0,这样做的好处是可以兼容部分C字符串函数