zoukankan      html  css  js  c++  java
  • 《Redis设计与实现》阅读笔记(二)--简单动态字符串

    简单动态字符串

    Redis只在一些无需对字符串进行修改的地方使用C字符串,大部分时候使用简单动态字符串simple dynamic string, SDS),字符串的抽象类型。二进制安全,可以存放任意格式的数据。

    定义

     1 源码(部分):
     2 struct __attribute__ ((__packed__)) sdshdr5 {
     3     unsigned char flags; /* 3 lsb of type, and 5 msb of string length */
     4     char buf[];
     5 };
     6 struct __attribute__ ((__packed__)) sdshdr8 {
     7     uint8_t len; /* used */
     8     uint8_t alloc; /* excluding the header and null terminator */
     9     unsigned char flags; /* 3 lsb of type, 5 unused bits */
    10     char buf[];
    11 };
    12 书中代码:
    13 struct sdshdr {
    14     int len;
    15     int free;
    16     char buf[];
    17 }

    这里以书中代码为基础,len为使用的字节数,free表示已分配但未使用的字节数。buf就是char型数组保存字符串。

    这里需要注意的是SDS保存的字符串沿用C字符串的格式,会在最末尾加一个''表示字符串结束,好处是可以复用C语言的函数库。

    举个例子:“hello” len为5,如果free为0,那么这个字符串一共使用6字节,''额外使用一个字节。

    由定义我们可以了解到,SDS的长度可以O(1)获得,而且他使用的内存不是长度+1。而且具有二进制安全的性质。

    空间分配策略

    Redis为了减少内存分配的次数,采用了空间预分配惰性空间释放两种策略。

    空间预分配

    当需要对SDS进行空间扩展的时候,SDS不仅会分配修改所必须的空间,还会进行预分配。

    如果修改后的len值小于1M,那么就会预分配和len同样大小的预留空间。也就是说经过修改和预分配len和free的值是相等的。这时候占有的字节数就是len+free+1。

    而如果修改后的len值大于等于1M,那么就只预分配1M空间。

    惰性空间释放

    当API需要缩短SDS保存的字符串,并不会立即释放多出来的字节,而是使用free记录下来。这样避免了内存重分配的操作,并为将来可能的增长提供了优化。

    如果确实需要释放未使用的空间,SDS也提供了相应的API。

    优点总结

    • 常数时间复杂度获取字符串长度
    • 杜绝缓冲区溢出
    • 减少在修改字符串长度时内存分配的次数
    • 二进制安全
    • 兼容部分C字符串函数
  • 相关阅读:
    Linux 共享库
    使用Visual Studio(VS)开发Qt程序代码提示功能的实现(转)
    ZOJ 3469 Food Delivery(区间DP)
    POJ 2955 Brackets (区间DP)
    HDU 3555 Bomb(数位DP)
    HDU 2089 不要62(数位DP)
    UESTC 1307 windy数(数位DP)
    HDU 4352 XHXJ's LIS(数位DP)
    POJ 3252 Round Numbers(数位DP)
    HDU 2476 String painter (区间DP)
  • 原文地址:https://www.cnblogs.com/Star-Dust-/p/10331765.html
Copyright © 2011-2022 走看看