features of the 1.1 Redis string
1. Binary security, the middle of the string can contain the ' \ S ' character.
2. Redis adds a ' + ' character at the end of the string, so the Redis string is compatible with the standard C string.
3. Use different types depending on the length of the string, and eliminate optimization alignment during compilation, saving space.
4. In order to increase the efficiency of string growth,Redis allocates extra space when extending the string length operation (sdsmakeroomfor), so that the next expansion of the length does not have to allocate space again. Note that Redis does not allocate additional space when a new string is created. Redis is based on the assumption that if a string has an extended length operation, then it is likely that it will also extend the length, so the space is then pre-allocated. For Redis, most strings do not need to be extended, so the space is not pre-allocated when the string is created.
1 struct__attribute__ ((__packed__)) SDSHDR5 {2UnsignedCharFlags/*3 LSB of type, and 5 MSB of string length*/3 Charbuf[];4 };5 struct__attribute__ ((__packed__)) Sdshdr8 {6uint8_t Len;/*used*/7Uint8_t Alloc;/*excluding the header and null terminator*/8UnsignedCharFlags/*3 LSB of type, 5 unused bits*/9 Charbuf[];Ten }; One struct__attribute__ ((__packed__)) sdshdr16 { Auint16_t Len;/*used*/ -Uint16_t Alloc;/*excluding the header and null terminator*/ -UnsignedCharFlags/*3 LSB of type, 5 unused bits*/ the Charbuf[]; - }; - struct__attribute__ ((__packed__)) Sdshdr32 { -uint32_t Len;/*used*/ +Uint32_t Alloc;/*excluding the header and null terminator*/ -UnsignedCharFlags/*3 LSB of type, 5 unused bits*/ + Charbuf[]; A }; at struct__attribute__ ((__packed__)) Sdshdr64 { -uint64_t Len;/*used*/ -Uint64_t Alloc;/*excluding the header and null terminator*/ -UnsignedCharFlags/*3 LSB of type, 5 unused bits*/ - Charbuf[]; -};
the role of __attrubte__ (packed) is to tell the compiler to cancel the optimized alignment of the structure during compilation and allocate it according to the actual number of bytes consumed.
1.2 techniques used in the implementation1.2.1 Calculating the address of the struct body
In the use of strings, we do not often use the string struct (for example, Sdshdr32), but instead use the string amount (BUF), so we need to find the address of the struct according to 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 Calculates the address of the flags according to BUF
Use subscript as negative to get the address of flags
1 StaticInlinevoidSdssetalloc (SDS s, size_t Newlen) {2 unsigned char = s[-1]; 3 Switch(flags&sds_type_mask) {4 Casesds_type_5:5 /*Nothing to do, the this type has the no total allocation info.*/6 Break;7 CaseSds_type_8:8SDS_HDR (8, s)->alloc =Newlen;9 Break;Ten Casesds_type_16: OneSDS_HDR ( -, s)->alloc =Newlen; A Break; - Casesds_type_32: -SDS_HDR ( +, s)->alloc =Newlen; the Break; - Casesds_type_64: -SDS_HDR ( -, s)->alloc =Newlen; - Break; + } -}
1.2.3 Storage space Pre-allocation
1 SDS Sdsmakeroomfor (SDS s, size_t Addlen) {2 void*sh, *newsh;3size_t avail =Sdsavail (s);4 size_t len, Newlen;5 CharType, Oldtype = s[-1] &Sds_type_mask;6 intHdrlen;7 8 /*Return ASAP If there is enough space left.*/9 if(Avail >= Addlen)returns;Ten OneLen =Sdslen (s); ASH = (Char*) ssdshdrsize (oldtype); -Newlen = (len+Addlen); - //if less than Sds_max_prealloc, the new length of the allocation is twice times the requested length the if(Newlen <Sds_max_prealloc) -Newlen *=2; - Else - /*Otherwise, add Sds_max_prealloc .*/ +Newlen + =Sds_max_prealloc; - + //calculate new type based on new length AType =Sdsreqtype (Newlen); at - /*Don ' t use type 5:the user was appending to the string and type 5 is - * able to remember empty space, so sdsmakeroomfor () must be called - * at every appending operation.*/ - if(type = = sds_type_5) type =Sds_type_8; - inHdrlen =sdshdrsize (type); - if(oldtype==type) { to //The old and new types are the same, re-assigned as the original template +newsh = S_realloc (sh, hdrlen+newlen+1); - if(newsh = = NULL)returnNULL; thes = (Char*) newsh+Hdrlen; *}Else { $ /*Since The header size changes, need to move the string forward,Panax Notoginseng * and can ' t use realloc*/ -Newsh = S_malloc (hdrlen+newlen+1); the if(newsh = = NULL)returnNULL; +memcpy ((Char*) Newsh+hdrlen, S, len+1); A s_free (SH); thes = (Char*) newsh+Hdrlen; +s[-1] =type; - Sdssetlen (S, Len); $ } $ Sdssetalloc (S, Newlen); - returns; -}
Redis Source Code Analysis 1----String SDS