redis源碼分析1----字串sds

來源:互聯網
上載者:User

標籤:

1.1 Redis字串的特點

  1. 二進位安全,字串中間可以包含‘\0‘字元。

   2. redis在字串的末尾會添加一個‘\0‘字元,所以redis字串與標準C的字串相容。

   3. 根據不同的字串長度使用不同的類型,並且取消編譯過程中的最佳化對齊,節省空間的。

   4. 為了提高字串增長的效率,redis在擴充字串長度操作(sdsMakeRoomFor)時的預分配了額外的空間,從而再下一次擴充長度時,不用再次分配空間。注意,redis並沒有在建立字串時分配額外的空間。redis基於一個假設:如果一個字串有了一次擴充長度的操作,那麼它之後很可能也會擴充長度,因此在這時預分配空間。對於redis來說,絕大部分字串是不需要擴充長度的,因此在建立字串時並不預分配空間。

 1 struct __attribute__ ((__packed__)) sdshdr5 { 2     unsigned char flags; /* 3 lsb of type, and 5 msb of string length */ 3     char buf[]; 4 }; 5 struct __attribute__ ((__packed__)) sdshdr8 { 6     uint8_t len; /* used */ 7     uint8_t alloc; /* excluding the header and null terminator */ 8     unsigned char flags; /* 3 lsb of type, 5 unused bits */ 9     char buf[];10 };11 struct __attribute__ ((__packed__)) sdshdr16 {12     uint16_t len; /* used */13     uint16_t alloc; /* excluding the header and null terminator */14     unsigned char flags; /* 3 lsb of type, 5 unused bits */15     char buf[];16 };17 struct __attribute__ ((__packed__)) sdshdr32 {18     uint32_t len; /* used */19     uint32_t alloc; /* excluding the header and null terminator */20     unsigned char flags; /* 3 lsb of type, 5 unused bits */21     char buf[];22 };23 struct __attribute__ ((__packed__)) sdshdr64 {24     uint64_t len; /* used */25     uint64_t alloc; /* excluding the header and null terminator */26     unsigned char flags; /* 3 lsb of type, 5 unused bits */27     char buf[];28 };

   __attrubte__ ((packed)) 的作用就是告訴編譯器取消結構在編譯過程中的最佳化對齊,按照實際佔用位元組數進行分配。

1.2  實現中使用的技巧  1.2.1 計算結構體的地址

   在使用字串的時候,我們並不會經常使用字串結構體(例如sdshdr32),而是會使用其中的字串量(buf),因此需要根據buf找到結構體的地址

1 #define SDS_HDR_VAR(T,s) struct sdshdr##T *sh = (void*)((s)-(sizeof(struct sdshdr##T)));2 #define SDS_HDR(T,s) ((struct sdshdr##T *)((s)-(sizeof(struct sdshdr##T))))3 #define SDS_TYPE_5_LEN(f) ((f)>>SDS_TYPE_BITS)
     1.2.2 根據buf計算flags的地址

  利用下標為負數來擷取flags的地址

 1 static inline void sdssetalloc(sds s, size_t newlen) { 2     unsigned char flags = s[-1];   3     switch(flags&SDS_TYPE_MASK) { 4         case SDS_TYPE_5: 5             /* Nothing to do, this type has no total allocation info. */ 6             break; 7         case SDS_TYPE_8: 8             SDS_HDR(8,s)->alloc = newlen; 9             break;10         case SDS_TYPE_16:11             SDS_HDR(16,s)->alloc = newlen;12             break;13         case SDS_TYPE_32:14             SDS_HDR(32,s)->alloc = newlen;15             break;16         case SDS_TYPE_64:17             SDS_HDR(64,s)->alloc = newlen;18             break;19     }20 }

 

  1.2.3 儲存空間預分配
 1 sds sdsMakeRoomFor(sds s, size_t addlen) { 2     void *sh, *newsh; 3     size_t avail = sdsavail(s); 4     size_t len, newlen; 5     char type, oldtype = s[-1] & SDS_TYPE_MASK; 6     int hdrlen; 7  8     /* Return ASAP if there is enough space left. */ 9     if (avail >= addlen) return s;10 11     len = sdslen(s);12     sh = (char*)s-sdsHdrSize(oldtype);13     newlen = (len+addlen);14     // 如果小於SDS_MAX_PREALLOC,則分配的新長度為請求長度的2倍15     if (newlen < SDS_MAX_PREALLOC)16         newlen *= 2;17     else18         /* 否則加上SDS_MAX_PREALLOC */19         newlen += SDS_MAX_PREALLOC;20 21     // 根據新長度計算新類型22     type = sdsReqType(newlen);23 24     /* Don‘t use type 5: the user is appending to the string and type 5 is25      * not able to remember empty space, so sdsMakeRoomFor() must be called26      * at every appending operation. */27     if (type == SDS_TYPE_5) type = SDS_TYPE_8;28 29     hdrlen = sdsHdrSize(type);30     if (oldtype==type) {31         // 新舊類型相同,則以原來的為模板重新分配32         newsh = s_realloc(sh, hdrlen+newlen+1);33         if (newsh == NULL) return NULL;34         s = (char*)newsh+hdrlen;35     } else {36         /* Since the header size changes, need to move the string forward,37          * and can‘t use realloc */38         newsh = s_malloc(hdrlen+newlen+1);39         if (newsh == NULL) return NULL;40         memcpy((char*)newsh+hdrlen, s, len+1);41         s_free(sh);42         s = (char*)newsh+hdrlen;43         s[-1] = type;44         sdssetlen(s, len);45     }46     sdssetalloc(s, newlen);47     return s;48 }

 

redis源碼分析1----字串sds

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.