我正在开发一个实现重复数据删除的开源项目。 (有关项目的链接,请参阅下面的两个超链接) 当前项目的性能非常好,但随着更多块被写入磁盘而降级。 这是由于HashManager。对于写入的每个块,hashmanager存储Hash-BlockId对。对于重复数据删除过程,需要具有给定散列的块标识符列表。 (使用的哈希是Crc32) 有关HashManager的界面,请参阅the source。
接口的当前implementation将列表存储在256个文件(crc& 0xFF)中,并将完整列表加载到内存中。当需要另一个列表时,将保存上一个列表并加载下一个列表。除了这可能导致内存耗尽这一事实外,这意味着降低性能。
有什么好的选择可以解决这个问题?
(只是为了清除:在重复数据删除之前完全检查块以查看它们是否匹配)
答案 0 :(得分:0)
我不是磁盘结构的专家,但我听说B-Tree经常用于实现存储在磁盘上的键值映射。所以我猜你可能有一个C-C的C-index索引,然后将某种链接存储到一个块id列表中。您也可以将列表组合到B树结构中,方法是有效地使用一个密钥,该密钥是CRC的串联,然后是块ID,然后在B树上进行有效的前缀/范围查询。
Wikipedia Page on B-Trees:“在计算机科学中,B树是一种树状数据结构,可以对数据进行排序,并允许在对数时间内进行搜索,顺序访问,插入和删除.B树是一种概括一个二叉搜索树,其中一个节点可以有两个以上的子节点。(Comer 1979,p.123)与自平衡二叉搜索树不同,B树针对读写大块数据的系统进行了优化。常用于数据库和文件系统。“
答案 1 :(得分:0)
如果您使用256个列表文件来存储crcs,第一个明显的步骤是将所有以列表0中的零字节开头的crcs,列表文件1中的所有字符串为1,等等。然后只在每个文件中存储crc的最后三个字节。这将节省25%的密钥存储空间,也可能加快处理速度。
要做的第二件事是制作一个4千兆比特的内存中标志数组,以显示列表中是否已注册一个4字节的crc。这将极大地加速向数组中添加新项目,因为您将知道是否需要首先查找现有条目 - 如果该位为零,则表示尚未使用crc。
根据数据域开发人员的一篇论文,这种不必要的查找最能减慢摄取过程(他们采用不同的避免方法)。
我假设您正在保存列表,因为您正在修改它们。我建议不要重写整个列表,而是将所有更改放在文件的末尾,这样就可以追加到文件的末尾而不是重写整个列表。使用链接列表结构,该结构以文件尾部的指针开头,使用每个追加文件将新标题写入文件末尾的列表中。您可以通过在列表上方写入一个带有删除标记的新条目来标记要删除的条目。然后定期您可以垃圾收集每个列表以减少列表大小(例如,每周或每月批处理一次)。您可以对列表修改执行相同的操作。只需写一个新条目来替换旧条目,或者带一个标志。然后定期垃圾收集以删除旧条目。
你可以做任何事情来构建列表,这样你就不需要每次都在内存中加载整个东西会加快速度。尽可能少地移动数据,尽可能少。
这是我在Stack Overflow上写的第一句话,所以请原谅我的帖子是否符合首选规范。
我在上面的说明中注意到我的回复编辑区域我不应该要求澄清,我想这是我可以有更多的乐趣只是猜测确切的问题是什么。我希望我的猜测很接近,我的答案包含有用的元素。