Yedis 是一款高性能的nosql数据库,旨在能在某些方面替代Redis。它由不著名码农、秦汉史历史学家、本站站长Yebangyu同学在业余时间独立开发完成。
Github请访问 这里 ,Python客户端请点击 这里
在Yedis中有两种字符串(或者更准确的说,字节流)实现: YedisString和YedisNormalString。代码都在 src/ds/yedis_string.h
和 src/ds/yedis_string.cpp
文件里。两种实现都设计为大小写不敏感。
以 /0
结尾的字符串实现,也就是说YedisNormalString中的字符串都是以 /0
结尾的。因此,对其施加任何类似于 strcmp
等传统C字符串函数都是安全的。
在实现时,针对短字符串,为了进一步优化效率,使用了柔性数组技术来提高cache命中。
class YedisNormalString { //...... private: static const int64_t CHAR_LEN_THRESHOLD = 48; int64_t len_; char *data_; char buffer_data_[0]; };
如果字符串长度小于48(48是怎么得来的?Yedis使用jemalloc来分配内存,以64字节为一个块单位来分配内存。64位系统里, len_
和 data_
各占用8个字节,cache line的大小一般为64字节,因此64 - 8 - 8 = 48。再次提醒,这里需要存储 /0
),则会使用embedded string,也就是说,此时字符串的内容会和 len_
、 data_
分配在一块连续的内存中。由于局部性原理,在读取时,它们都会读到cache中,减少了cache miss,大大提高了性能。
不管字符串长度如何,不管是否使用柔性数组技术来提高cache 命中, data_
都会被设置为指向字符串的首地址。因此,外部总可以通过 data_
访问到字符串,
在YedisString中的字符串存储,都不以 /0
结尾。因此,不能对其施加 strlen
等传统C字符串函数。
YedisString中特别考虑了append函数的实现。为了减少内存分配,每次在append时,都会首先判断当前缓冲区是否够用,如果够用直接append;否则,这时候需要重新分配内存。注意,这时候我们会多分配一倍的内存,以防止下次append时不必要的内存分配动作。当然,这可能会造成内存浪费,但是对于优化时间消耗具有重要意义。