Redis设计与实现(1-字符串)
每个sds.h/sdshdr结构表示一个SDS值:
struct sdshdr{ |
free属性的值为0,表示这个SDS没有分配任何未使用空间。
len属性的值为5,表示这个SDS保存了一个五字节长的字符串。
buf属性是一个char类型的数组,最后一个字节保存空字符’\0’。
SDS遵循C字符串以空字符结尾的惯例,保存空字符的1字节空间不计算在SDS的len属性里面。
示例:
SDS遵循C字符串以空字符结尾的惯例,保存空字符的1字节空间不计算在SDS的len属性里面。
通过 len 属性,SDS
获取字符串长度时,其时间复杂度为 O(1) 。
通过检查SDS的空间是否满足修改所需的要求,杜绝了缓冲区溢出的可能性。
当 SDS API 需要对SDS
进行修改时,API 会先检查SDS
的空间是否满足修改所需的要求,如果不满足的话,API 会自动将SDS
的空间扩展至执行修改所需的大小,然后才执行实际的修改操作。
通过未使用空间解除了字符串长度和底层数组长度之间的关联,减少了内存重分配的次数。
在SDS
中,buf 数组的长度不一定就是字符数量加一,数组里面可以包含未使用的字节,而这些字节的数量就由SDS
的 free 属性记录。
通过未使用空间,SDS
实现了空间预分配和惰性空间释放两种优化策略。
空间预分配用于优化SDS
的字符串增长操作:当SDS
的 API 对一个SDS进行修改,并且需要对SDS
进行空间扩展的时候,程序不仅会为SDS
分配修改所必要的空间,还会为SDS
分配额外的未使用空间。
惰性空间释放用于优化SDS
的字符串缩短操作:当SDS
的 API 需要缩短SDS
保存的字符串时,程序并不立即使用内存重分配来回收缩短后多出来的字节,而是使用 free 属性将这些字节的数量记录起来,并等待将来使用。
SDS
是二进制安全的。
所有 SDS API 都会以处理二进制的方式来处理SDS
存放在 buf 数组里的数据。