首页 > 解决方案 > 包含用于初始化 Trie 结构的大型源文件的 Rust crate 无法编译 (OOM)

问题描述

我已经Trie实现了一个结构Rust,我从其他人那里获取了它,并且似乎工作得很好:

pub struct Trie<K, V>
where
    K: std::fmt::Debug + Eq + Hash + Clone,
    V: std::fmt::Debug + Clone,
{
    value: Option<V>,
    children: HashMap<K, Trie<K, V>>,
}

impl<K, V> Trie<K, V>
where
    K: std::fmt::Debug + Eq + Hash + Clone,
    V: std::fmt::Debug + Clone,
{
    pub fn new() -> Trie<K, V> {
        Trie {
            value: None,
            children: HashMap::new(),
        }
    }

    pub fn insert(&mut self, path: Vec<K>, v: V) {
        if path.is_empty() {
            match self.value {
                Some(_) => panic!("key exists"),
                None => {
                    self.value = Some(v);
                }
            }
            return;
        }

        self.children
            .entry(path[0].clone())
            .or_insert(Trie::new())
            .insert(path[1..].to_vec(), v)
    }

    pub fn fetch_or_default(&self, path: Vec<K>, default: V) -> V {
        let value = self.value.clone().unwrap_or(default);
        match path.len() {
            0 => value,
            _ => match self.children.get(&path[0]) {
                Some(child) => child.fetch_or_default(path[1..].to_vec(), value),
                None => value,
            },
        }
    }
}

我有一个特殊的文件,我在其中基于包含 150k 个单词的字典初始化 Trie 的实例,我为每个字典分配一个 0 到 150 之间的数字。

数据是通过 JavaScript 生成的,所以它并不是不可能的巨大,但由于某种原因,Rust 编译器无法处理它,并且尽管我的计算机有 16Gb 内存 + 2Gb 交换(它在崩溃前完全使用),但内存崩溃了。

use crate::data::*;

/*
a.reduce((str,ai,i) => { return str + ai.map((w,i) => `    //${w}\n    words_trie.insert(vec![' ',${w.split('').reverse().map(c => `'${c==`'`?`\\`:''}${c}'`).join(',')}], ${i});`).join('\n') + '\n' }, '');
*/

pub fn into(words_trie: &mut Trie<char, usize>) {
    // SPECIAL LINE, DO NO REPLACE BY ABOVE FORMULA
    words_trie.insert(vec![], 150);
    // ================================================
    //'n
    words_trie.insert(vec![' ', 'n', '\''], 0);
    ...
    //(150 000 times a comment followed by an insertion line)
    ...
}

我收到的错误消息如下,但这只是工作中的 OOM 杀手:

process didn't exit successfully: `rustc --edition=2018 --crate-name postag_nl_v1 src/main.rs --color always --crate-type bin --emit=dep-info,link -C debuginfo=2 -C metadata=f33cf4c96979227f -C extra-filename=-f33cf4c96979227f --out-dir /home/fremy/Documents/postag_nl_v1/target/debug/deps -C incremental=/home/fremy/Documents/postag_nl_v1/target/debug/incremental -L dependency=/home/fremy/Documents/postag_nl_v1/target/debug/deps` (signal: 9, SIGKILL: kill)

如何在不使编译器崩溃的情况下根据字典初始化我的 Trie?

[编辑] 这是一个最小的复制,带有虚拟数据:

https://gist.github.com/FremyCompany/1f6132441338f8b219d961c7254bd8ac#file-main-rs

https://1drv.ms/u/s!AhVrPgyThAkTgQ8v2U99Ffzug7rJ [1Mb 压缩包]

标签: rust

解决方案


推荐阅读