#增量计算 #记忆化 #增量 #追踪 #约束

comemo

通过约束记忆化实现增量计算

7 个不稳定版本

0.4.0 2024 年 3 月 7 日
0.3.1 2023 年 11 月 27 日
0.3.0 2023 年 5 月 16 日
0.2.2 2023 年 4 月 17 日
0.1.0 2022 年 10 月 15 日

#23缓存

Download history 2508/week @ 2024-03-14 1455/week @ 2024-03-21 1208/week @ 2024-03-28 1114/week @ 2024-04-04 999/week @ 2024-04-11 833/week @ 2024-04-18 961/week @ 2024-04-25 953/week @ 2024-05-02 1028/week @ 2024-05-09 1822/week @ 2024-05-16 1372/week @ 2024-05-23 1005/week @ 2024-05-30 1428/week @ 2024-06-06 1227/week @ 2024-06-13 1365/week @ 2024-06-20 946/week @ 2024-06-27

5,090 每月下载量
33 个包 中使用 (21 个直接使用)

MIT/Apache

47KB
890

comemo

Crates.io Documentation

通过约束记忆化实现增量计算。

[dependencies]
comemo = "0.4"

一个 记忆化 函数会缓存其返回值,这样它就只需要对一组唯一的参数执行一次。这使其成为一个优秀的优化工具。然而,基本的记忆化相当有限。对于像增量编译器这样的更高级用例,它缺乏必要的粒度。考虑,例如,简单的 .calc 脚本语言。这种语言中的脚本由数字之和和引用其他 .calc 脚本的 eval 语句组成。一些例子包括

  • alpha.calc: "2 + eval beta.calc"
  • beta.calc: "2 + 3"
  • gamma.calc: "8 + 3"

我们可以轻松编写一个计算 .calc 文件输出的解释器

/// Evaluate a `.calc` script.
fn evaluate(script: &str, files: &Files) -> i32 {
    script
        .split('+')
        .map(str::trim)
        .map(|part| match part.strip_prefix("eval ") {
            Some(path) => evaluate(&files.read(path), files),
            None => part.parse::<i32>().unwrap(),
        })
        .sum()
}

impl Files {
    /// Read a file from storage.
    fn read(&self, path: &str) -> String {
        ...
    }
}

但是,如果我们想使这个解释器 增量,也就是说,只有当脚本或其依赖项发生变化时才重新计算脚本的结果,该怎么办?基本的记忆化无法帮助我们,因为解释器需要整个文件集作为输入——这意味着任何文件的变化都会使所有记忆化的结果无效。

这就是 comemo 发挥作用的地方。它实现了具有更细粒度访问跟踪的 约束记忆化。要使用它,我们只需

  • #[memoize] 属性添加到 evaluate 函数。
  • #[track] 属性添加到 Files 的 impl 块中。
  • files 参数包裹在 comemo 的 Tracked 容器中。

这指示 comemo 记忆化评估并自动跟踪在记忆化调用期间的所有文件访问。因此,只要其依赖项保持不变,我们就可以重用 .calc 脚本评估的结果——即使其他文件发生变化。

use comemo::{memoize, track, Tracked};

/// Evaluate a `.calc` script.
#[memoize]
fn evaluate(script: &str, files: Tracked<Files>) -> i32 {
    ...
}

#[track]
impl Files {
    /// Read a file from storage.
    fn read(&self, path: &str) -> String {
        ...
    }
}

有关完整示例,请参阅 examples/calc.rs

许可证

此软件包同时受 MIT 和 Apache 2.0 许可证的许可。

依赖项

~0.8–6.5MB
~31K SLoC