-
Notifications
You must be signed in to change notification settings - Fork 437
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add hash index to speed up searching #101
base: master
Are you sure you want to change the base?
Conversation
LianYangCn
commented
Sep 9, 2021
- This patch allows you to boost searching from O(n) to O(1)
- Because the implementation is based on the hash, it has to take more memory to store the index data.
- And each key-value entry takes 4 bytes.
- More details please reference the "Demos/Linux"
_fdb_kv_load() 函数里面本来就会更新缓存,刚开始没有注意到 这次删除了重复更新Hash的代码
各位大佬们,出来围观吊打我吧 |
感谢你的 PR,这两天有些忙,我要晚点看下哈 |
} | ||
|
||
{ | ||
#endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
简单点,name_crc 对 FDB_KV_CACHE_TABLE_SIZE 取余,作为 hash index ,这种效果如何?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
不是特别明白你的意思,我想法是这样的
name_crc 对 FDB_KV_CACHE_TABLE_SIZE 取余,作为 hash index
, 是不是说,直接使用CRC32 作为 hash index 的字符串hash算法,如果你是这个意思,那么肯定是可以的,效果应该也不错,你可以参考这里- 关于 string 的 hash 算法是用 CRC32 还是 CRC32+Robert Jenkins (PR 里面使用的方法)或者其他hash算法,我觉得都不算大问题,可以随时替换,但是减少对撞肯定是第一目标。不过,坦白的说 CRC32+Robert Jenkins 是有点慢的!
- 这里保留了原来的 CACHE 机制是因为,hash index 空间的大小和 字符串 hash 算法共同决定了对撞的概率,但是如果发生对撞,常见的解决方法有两个,一个是通过扩大 hash index 空间,然后再 re-hash,还有一个办法就是 hash index 空间不变了,用另外一个可靠(即不是依靠概率,没有对撞可能性的方法),这个时候原来的 CACHE 就可以登场,原来的 CACHE 就可以解决 hash index 带来的概率性冲撞问题,这样可靠性就可以大大增加
- 那么为什么 不用 re-hash 的方法的呢?re-hash 的方法意味着, hash index 的内存空间大小是动态变化的,在嵌入式设备中,内存空间动态变化,是比较难以管理的,所以放弃使用 re-hash 来解决冲撞问题
- 如果 hash index + CACHE 能以接近 100% 的准确度(也就是上面提到的双重保证),那么我们在 更新/添加 Key Value 的时候就可以直接信任这套机制(指 hash index + CACHE),如果在 hash index + CACHE 中都找不到,那说明 这个 Key 不在 FlashDB 中,如果是添加操作,这样写入速度也会极大的提高,因为现在的方法是如果 CACHE 中没有,还要遍历一遍 FlashDB,这样才能确定 Key 有没有存在数据库中。根据我在 ESP32 中的测试,当数据量到 2000条左右的时候,添加一条新数据,耗时已经超过1秒钟,每一次添加都要搜索前面的2000条或者更多数据,这种回溯真的是惨绝人寰,不环保,太耗电
- hash index 和 CACHE 作为两种完全不同的索引机制,CACHE 更加简单可靠,适用于小数据(大约是小于1000条); 而 hash index 稍微复杂,会占用更多的内存(一条数据占用4字节,预留总内存 = 预估总数据条数x1.25x4,5000 条记录最好预留 24.414KB 的内存),又有 CACHE 加持,这就是一个活脱脱的数据库,要知道,SQLite 第一版也是用 hash index,后来才换成 B tree
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
使用 name_crc 取余,主要是考虑比较小的改动成本,保证 FlashDB 的轻量级特色。当然,这样对于碰撞的处理会欠佳。
原本 FlashDB 的 cache 是具备 LRU 特色的,用的越频繁保留时间越久,也能降低资源占用,不用全部缓存。
另外,现在的问题我稍微整理一下,你看下对不对:
- 1、初始化时,如果 FlashDB 中的 KV 较多,初始化时间过长
- 2、KV 数量超过 1K 时,查询时间会超过 500MS ,体验不好
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
我明白你的意思了,但是我主要是考虑,CACHE 已经稳定的话不要动,CACHE 的 LRU 也是特色,非常好,而且配合 hash index 能获得更好的性能
现在我在 ESP32 上面测试
1、初始化时,如果 FlashDB 中的 KV 较多,初始化时间过长
这个问题已经证实是 hash 太慢造成的,现在已经解决 但是PR 里面没有, #99 你说 murmur,也行,都是好算法
2、KV 数量超过 1K 时,查询时间会超过 500MS ,体验不好
这个问题引入 hash index 开始就没有再出现过,O(1)可不是盖的
3、如果说现在 PR 还不完善的地方就是,没有考虑对撞冲突的问题,所以添新 entry 还是非常非常非常非常慢的,现在比较像 hash cache 等把这条腿补充完成了,才算一个真正的 hash index
4、我觉得正如你在 #99 所说 ,cache + hash index 独立出来是一个不错的想法,我刚开始也是这么干的,后来我觉得有点麻烦,哈哈,就偷了个懒,但是我觉得更重要的是把这个独立成一个分支,把咱这个PR纳入到“官方”正统,这样接着干才有意思,不然,那岂不是白忙活,因为我要是自己用,代码肯定写的比这个还简单,我会算的死死的,不会出现这么多 if else 对我来说够用就行
准备投入实际使用了 |
👍, 我 十一 的时候再把整体框架梳理一下,后续 索引算法 应该会独立文件出来 |