#memoization #incremental #tracked #constraints #incremental-computation

comemo-macros

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日

#385缓存

Download history 2516/week @ 2024-03-14 1464/week @ 2024-03-21 1202/week @ 2024-03-28 1113/week @ 2024-04-04 1002/week @ 2024-04-11 837/week @ 2024-04-18 970/week @ 2024-04-25 957/week @ 2024-05-02 1034/week @ 2024-05-09 1821/week @ 2024-05-16 1372/week @ 2024-05-23 1007/week @ 2024-05-30 1427/week @ 2024-06-06 1240/week @ 2024-06-13 1372/week @ 2024-06-20 944/week @ 2024-06-27

5,107 每月下载量
34 个 Crates 中使用(通过 comemo

MIT/Apache 许可

29KB
497

comemo

Crates.io Documentation

通过约束式缓存实现增量计算。

[dependencies]
comemo = "0.4"

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

  • 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 许可证的许可。

依赖项

~305–760KB
~18K SLoC