哪里使用了C字符串?
不需要修改的字符串字面量
哪里用到了SDS?
保存数据库中的字符串值(包括key和value)
缓冲区(AOF缓冲区、输入输出缓冲区)
认识SDS?
struct sdshdr {
unsigned int len;//记录buf数组中已使用字节的数量,等于SDS所保存字符串的长度
unsigned int free;//记录buf数组中未使用字节的数量
char buf[];//字节数组,用于保存字符串
}
注意:SDS遵循C字符串以空字符结尾的惯例,以便于直接重用一部分C字符串函数库里函数。
SDS与C字符串的区别?
获取字符串长度为O(1)/C为O(N)
SDS杜绝缓冲区溢出(SDS API在修改时,会先检查空间是否满足要求,不满足会自动扩展)
此处留问题:如何扩展?空间分配策略?
减少修改字符串时带来的内存重分配次数-->通过free属性实现以下两种优化策略
空间预分配:用于优化SDS字符串增长操作。
不仅分配修改所必须要的空间,还会分配额外的未使用空间。
未使用空间数量规则如下:
修改后的SDS长度<1MB:free=len
修改后的SDS长度>1MB:free=1MB
惰性空间释放:用于优化SDS字符串缩短操作。
不会立即回收多出来的字节,而是用free属性记录起来,等待将来使用,有API可以真正释放空间。
二进制安全
SDS API
sdsnew:创建一个包含给定C字符串的SDS,O(N),N为给定C字符串的长度
sdsempty:创建一个不包含任何内容的空SDS,O(1)
sdsfree:释放给定的SDS,O(N),N为被释放SDS的长度
sdslen:返回SDS的已使用空间字节数,O(1),len属性
sdsavail:返回SDS的未使用空间字节数,O(1),free属性
sdsdup:创建一个给定SDS的副本,O(N),N为给定SDS的长度
sdsclear:清空SDS保存的字符串内容,O(1)
sdscat:将给定C字符串拼接到SDS字符串的末尾,O(N),N为被拼接C字符串的长度
sdscatsds:将给定SDS字符串拼接到另一个SDS字符串的末尾,O(N),N为被拼接SDS字符串的长度
sdscpy:将给定的C字符串复制到SDS里面,覆盖SDS原有的字符串,O(N),N为被复制C字符串的长度
sdsgrowzero:用空字符将SDS扩展至给定长度,O(N),N为扩展新增的字节数
sdsrange:保留SDS给定区间内的数据,不在区间内的数据会被覆盖或清除,O(N),N为被保留数据的字节数
sdstrim:接受一个SDS和一个C字符串作为参数,从SDS左右两端分别移除所有在C字符串中出现过的字符,O(M*N),M为SDS长度,N为给定c字符串的长度
sdscmp:对比两个SDS字符串是否相同,O(N),N为两个SDS中较短的那个SDS的长度复制代码
转载于:https://juejin.im/post/5bd15c2af265da0aca334e09