redis 数据结构 sds
sdshdr数据结构
结构体代码
struct __attribute__ ((__packed__)) sdshdr32 { uint32_t len; /* 当前字符串的长度 */ uint32_t alloc; /* 分配的空间大小,不包括头部(len alloc flags)跟结束符(null \0) */ unsigned char flags; /* 用三个bit位表示目前存在的6种sdshdr数据结构类型 */ char buf[]; /*字符串空间,这里不使用char* buf是为了一次内存操作就能分配释放sdshdr,下面会讲到/ };
- sdshdr数据结构类型一共有sdshdr5(暂时未使用)、sdshdr8、sdshdr16、sdshdr32、sdshdr64, 并且用flag来表示类型。
- redis的源码中一般用字符串来引用sdshdr结构体,使用sds[-1]即可获取结构体类型,由结构体类型可获取结构体首地址。
基本函数
hacking sds
staticbuf
/** * 类似于sdscatprintf()但是返回 va_list而不可变 * @param s * @param fmt * @param ap * @return */ sds sdscatvprintf(sds s, const char *fmt, va_list ap) { va_list cpy; char staticbuf[1024], *buf = staticbuf, *t; size_t buflen = strlen(fmt)*2; /* We try to start using a static buffer for speed. * If not possible we revert to heap allocation. */ /** * 出于效率考虑 */ if (buflen > sizeof(staticbuf)) { buf = s_malloc(buflen); if (buf == NULL) return NULL; } else { buflen = sizeof(staticbuf); } /* Try with buffers two times bigger every time we fail to * fit the string in the current buffer size. */ while(1) { buf[buflen-2] = '\0'; va_copy(cpy,ap); vsnprintf(buf, buflen, fmt, cpy); va_end(cpy); if (buf[buflen-2] != '\0') { if (buf != staticbuf) s_free(buf); buflen *= 2; buf = s_malloc(buflen); if (buf == NULL) return NULL; continue; } break; } /* Finally concat the obtained string to the SDS string and return it. */ t = sdscat(s, buf); if (buf != staticbuf) s_free(buf); return t; }
staticbuf默认分配1024的栈空间,如果所请求的空间不大,则可以直接使用该空间,无需动态分配内容,提高时间效率。
未完待续