小知识,大挑战!本文正在参与“程序员必备小知识”创作活动
SDS与C字符串区别
杜绝缓冲区溢出
C字符串不记录自身长度带来的另一个问题就是容易造成缓冲区溢出。
当SDS API需要对SDS进行修改的时候,API会检查SDS的空间是否满足修改所需的要求,如果不满足,API自动将SDS的空间扩展至执行修改所需的大小,然后才执行实际的修改操作,所以使用SDS既不需要手动修改SDS的空间大小,也不会出现缓冲区溢出的问题
减少修改字符串时带来的内存重分配次数
C字符串并不记录自身长度,每次增长或缩短字符串,都会对C字符串的数据进行一次内存的重分配操作:
- 增长字符串,程序需要先通过内存重分配来扩展底层数组的空间大小,如果没有就会产生缓冲区溢出
- 缩短字符串,程序需要通过内存重分配释放字符串,如果没有产生内存泄露
SDS通过未使用空间,空间预分配和惰性空间释放
空间预分配
空间预分配用于优化SDS的字符串增长操作:当SDS的API对SDS进行修改,并且需要对SDS进行空间扩展的时候,程序不仅会对SDS分配修改所需的空间,还会为SDS分配额外未使用的空间
分配未使用空间大小:
- 如果修改后的SDS长度小于1MB,程序分配和len属性同样大小的未使用空间,例如修改后长度为13字节,那么将会分配13+13+1的未使用空间,1表示保存空字符
- 如果修改后的SDS长度大于等于1MB,程序会分配1MB的未使用空间,例如修改后长度为30MB,那么会分配30MB+1MB+1
通过空间预分配,Redis减少了内存重分配的次数,当空间不足的时候才会进行重分配,如果未使用空间足够,直接使用未使用的空间,无需执行内存重分配。
惰性空间释放
惰性空间释放是用于优化SDS的字符串缩短操作:当SDS的API需要缩短SDS保存的字符串时,程序并不立即内存重分配来回收缩短之后多出来的字节,而是使用free属性将这些字节的数量记录下来,等待将来增长的时候使用
通过惰性空间释放策略,SDS避免了缩短字符串时所需的内存重分配操作,并为将来可能有的增长操作提供优化。SDS有相关API,当我们真正需要释放SDS的未使用空间时可以释放,无需担心惰性空间释放策略造成内存浪费。
总结
今天主要给大家讲了一下SDS与C字符串的两个方面的异同,SDS杜绝缓冲区溢出和减少修改字符串时带来的内存重分配次数,减少修改字符串时带来的内存重分配次数方面SDS通过增长时候的空间预分配和减少时候的惰性空间释放来进行了优化。