在Rust

时间:2016-04-17 12:50:16

标签: memory hashmap rust

我试图通过在其上使用固定大小的滑动窗口来解析一个很长的文件。对于每个这样的窗口,我希望将其作为具有自定义结构作为值的键插入HashMap,或者修改窗口的现有值。我的主要问题是内存使用,因为它应该扩展到非常大的数量(高达数十亿个不同的窗口),我想重用现有的密钥。

我想将窗口(或更具体的字节)附加到向量并将索引用作HashMap中的键,但使用索引下的窗口进行哈希计算和密钥比较。因为窗口是重叠的,我只会附加新窗口的部分(如果我有一个输入AAAB和大小3我将有2个窗口:AAA和AAB,但只会存储4个字节--AAAB;窗口会有索引分别为0和1),这是没有用窗口本身键入HM的原因。

这里是简化的伪代码,其中我省略了最小输入问题:

let file =  // content of the file on which i can call windows()
let vec = Rc::new(RefCell::new(Vec::new()));  // RefCell allows me to store Rc in the hashmap while mutating the underlying vector
let hm: HashMap<KeyStruct, ValueStruct> = HashMap::new();
for i in file.windows(FIXED_SIZE) {
    let idx = vec.len();
    vec.borrow_mut().push(i);
    if hm.contains_key(KeyStruct::new(idx)) {
        // get the key associated with i
        // modify the value associated with i
        // do something with the key
        vec.borrow_mut().pop();  // window is already in the vector
    }
    else {
        hm.insert(KeyStruct::new(idx), ValueStruct::new(...));
    }
}

我提出了两种不同的方法:修改现有的HashMap实现以使其按预期工作,或使用自定义结构作为HashMap的键。由于我只使用一个向量来存储窗口,因此我可以在Rc中为其存储HashMap,然后将其用于查找。

我还可以创建一个包含Rc和索引的结构,并将其用作HashMap的键。后一个解决方案适用于vanilla HashMap,但会将大量冗余Rc存储到同一个向量中。我还想过将一个静态指针存储到Rc,然后在Rc块中得到unsafe,但我必须保证堆栈上Rc的位置永远不会变化,我不确定我是否可以保证。

我尝试实现第一种方法(自定义HashMap),但事实证明Bucket使用了很多门控功能,我无法使用稳定的编译器。

更糟糕的是,我希望在成功查找时获得HashMap中已有的密钥(因为不同的索引可以存储同一个窗口,{{1} } / hash将是相同的)并在值结构中使用它。我无法使用cmp提供的API找到相应的方法 - 我最接近的是使用HashMap,其中包含entry(),但它没有&# 39;有任何方法可以检索密钥,并且无法通过不安全的内存查找来获取密钥,因为OccupiedEntry上的文档说明在默认表示中不保证结构中的顺序。我可以将键(或仅索引)存储在值struct中,但是每个条目添加另一个repr()个字节,只是以可达到的方式存储索引/键,无论哪种方式都保存该条目

我的问题是:

  • 是否可以编译/重用非pub的std :: collections部分,这样我可以修改size_of::<usize>()的几个方法并编译整个项目?
  • HashMap成功查找后,有没有办法获取密钥? (我甚至found out libs团队决定反对HashMap实施方法,这样我就可以获得密钥...)
  • 您能看到我提到的解决方案的替代方案吗?

修改

为了澄清问题,让我们考虑一个简单的例子 - 输入ABABCBACBC,窗口大小为2. 我们应该将索引作为Entry的关键,它应该得到窗口 - 作为从该索引开始的窗口的大小字节数:使用向量[A,A,C],索引1和窗口大小2 HashMap应该尝试查找AC的散列/密钥。

我们得到这样的窗口:

HashMap

第一对是AB,我们将它附加到空向量中并给它一个0的索引。

AB -> BA -> AB -> BC -> CB -> BA -> AC -> CB -> BC

下一对是BA:

  1. 以vec = [A,B]
  2. 开头
  3. 使用此处未显示的算法,我知道我在最后插入的窗口(AB)和当前窗口(BA)之间有一个共同的部分,即B
  4. 将窗口的一部分附加到现有向量,因此我们有vec = [A,B,A]
  5. 使用索引1作为窗口索引
  6. 执行查找
  7. 尚未找到,因此将新密钥val插入vec = [A, B] hm = [(0, val)]
  8. vec = [A,B,A] hm = [(0,val0),(1,val1)]

    接下来是AB窗口:

    1. 我们再次有一个共同的部分 - A
    2. 追加:vec = [A,B,A,B]
    3. 使用索引2进行查找
    4. 它是成功的,所以我应该删除新插入的窗口部分并获取向量内的窗口索引 - 在这种情况下为0
    5. 修改价值,用钥匙等做点什么......

      vec = [A,B,A] hm = [(0,val0_modified),(1,val1)]

    6. 在循环输入后,我应该最终得到:

      HashMap

      和对的索引可以表示为:[(AB,0),(BA,1),(BC,3),(CB,4),(AC,6)]

      想要修改密钥。除了在查找/插入期间推/弹窗口外,我也不想修改矢量。

      旁注:尽管在将所有内容都放入向量后,我仍然在此特定示例中有冗余信息,但在使用原始数据时却不会出现这种情况。

0 个答案:

没有答案