Redis源码分析: String(SDS)容量调整分析
整体思路:
1 惰性缩容。不释放空间,留给到期释放等机制释放。
2 加倍扩容。在需要空间达1M之前按新空间两倍分配空间,否则按新空间大小+1M分配。注意,1M=1024*1024*Char。Char可以是5bits/8bits/16bits/32bits/64bits
具体代码块:
惰性缩容:https://github.com/antirez/sds/blob/master/sds.c line374-390
/* Grow the sds to have the specified length. Bytes that were not part of * the original length of the sds will be set to zero. * * if the specified length is smaller than the current length, no operation * is performed. */ sds sdsgrowzero(sds s, size_t len) { size_t curlen = sdslen(s); if (len <= curlen) return s; s = sdsMakeRoomFor(s,len-curlen); if (s == NULL) return NULL; /* Make sure added region doesn't contain garbage */ memset(s+curlen,0,(len-curlen+1)); /* also set trailing \0 byte */ sdssetlen(s, len); return s; }
加倍扩容: https://github.com/antirez/sds/blob/master/sds.c line204-220
/* Enlarge the free space at the end of the sds string so that the caller * is sure that after calling this function can overwrite up to addlen * bytes after the end of the string, plus one more byte for nul term. * * Note: this does not change the *length* of the sds string as returned * by sdslen(), but only the free buffer space we have. */
sds sdsMakeRoomFor(sds s, size_t addlen) { void *sh, *newsh; size_t avail = sdsavail(s); size_t len, newlen; char type, oldtype = s[-1] & SDS_TYPE_MASK; int hdrlen; /* Return ASAP if there is enough space left. */ if (avail >= addlen) return s; len = sdslen(s); sh = (char*)s-sdsHdrSize(oldtype); newlen = (len+addlen); if (newlen < SDS_MAX_PREALLOC) newlen *= 2; else newlen += SDS_MAX_PREALLOC;
其中:https://github.com/antirez/sds/blob/master/sds.h line36
#define SDS_MAX_PREALLOC (1024*1024)
源码见: