Memory 降低Rust中HashMap的内存使用率

Memory 降低Rust中HashMap的内存使用率,memory,hashmap,rust,Memory,Hashmap,Rust,我试图通过使用固定大小的滑动窗口来解析一个很长的文件。对于每个这样的窗口,我要么将其插入到HashMap中作为键,将custom struct作为值,要么修改窗口的现有值。我的主要问题是内存使用,因为它应该扩展到非常大的数量(多达数十亿个不同的窗口),我想重用现有的密钥 我希望将窗口(或更具体地说是字节)附加到向量,并将索引用作HashMap中的键,但使用索引下的窗口进行哈希计算和键比较。因为窗口是重叠的,所以我将只附加新窗口的一部分(如果我有一个输入AAAB和大小3,我将有两个窗口:AAA和A

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

我希望将窗口(或更具体地说是字节)附加到向量,并将索引用作
HashMap
中的键,但使用索引下的窗口进行哈希计算和键比较。因为窗口是重叠的,所以我将只附加新窗口的一部分(如果我有一个输入AAAB和大小3,我将有两个窗口: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(...));
    }
}
第一对是AB,我们将它附加到空向量中,并给它一个0的索引

vec = [A, B]
hm = [(0, val)]
下一对是BA:

  • 从vec=[A,B]开始
  • 使用这里未显示的算法,我知道在最后插入的窗口(AB)和当前窗口(BA)之间有一个公共部分,即B
  • 将窗口的一部分附加到现有向量,这样我们就得到了vec=[A,B,A]
  • 使用索引1作为窗口的索引执行查找
  • 由于未找到它,因此新的键val被插入到
    HashMap
  • 向量=[A,B,A] hm=[(0,val0),(1,val1)]

    接下来是窗口AB:

  • 我们又有了一个共同点——a
  • 附加:vec=[A,B,A,B]
  • 使用索引2查找
  • 它是成功的,所以我应该删除窗口的新插入部分,并获取窗口内部向量的索引-在本例中为0
  • 修改值,用键做一些事情等等

    向量=[A,B,A] hm=[(0,val0_修改),(1,val1)]

  • 在循环此输入之后,我应该得到:

    vec = [A, B, A, B, C, B, A, C]
    
    成对的指数可以表示为:[(AB,0),(BA,1),(BC,3),(CB,4),(AC,6)]

    我不想修改关键点。我也不想修改向量,除了在查找/插入期间推/弹出窗口


    旁注:尽管我在将所有内容放入vector后,在这个特定示例中仍然有冗余信息,但在处理原始数据时,情况并非如此。

    恐怕我不明白您试图做什么(我可以看出您对此考虑了很多,但不幸的是,您尝试的解决方案在某种程度上扰乱了解释。)是否可以用一个键值数组和几个“回合”来演示您想要做什么循环的一部分?你是在试图修改密钥吗?Re#2:Rust Nightly包含一个不稳定的
    key
    方法,关于
    Occuppidentry
    :@Dogbert:小心。我担心Fuine试图修改密钥,这将是一个非常糟糕的主意……你没有hashmap
    {“AB”=>val0,“BC”=>val1,…}
    而不是使用这个向量查找?我在值结构中重复使用了很多键,如上所述,保持一个int比保持和重复使用一个大小为50-100的窗口产生更小的内存开销(这大约是每个键使用50+24字节,而不是在64位机器上使用8字节)(如果我使用Rc+idx struct,则为16)。该解决方案确实应该扩大规模。恐怕我不明白您试图做什么(我可以看出您对此考虑了很多,但不幸的是,您尝试的解决方案在某种程度上扰乱了解释)。是否可以用一个键值数组和几个“轮次”来演示您想要做的事情循环的一部分?你是在试图修改密钥吗?Re#2:Rust Nightly包含一个不稳定的
    key
    方法,关于
    Occuppidentry
    :@Dogbert:小心。我担心Fuine试图修改密钥,这将是一个非常糟糕的主意……你没有hashmap
    {“AB”=>val0,“BC”=>val1,…}
    而不是使用这个向量查找?我在值结构中重复使用了很多键,如上所述,保持一个int比保持和重复使用一个大小为50-100的窗口产生更小的内存开销(这大约是每个键使用50+24字节,而不是在64位机器上使用8字节)(如果我使用Rc+idx结构,则为16)。该解决方案应该可以真正扩展。
    vec = [A, B, A, B, C, B, A, C]