2个不稳定版本

0.2.0 2024年7月28日
0.1.0 2024年7月22日

#13#happy

Download history 117/week @ 2024-07-19 152/week @ 2024-07-26 9/week @ 2024-08-02

每月下载量:278
iex 中使用

MIT/Apache

20KB
468

Rust的惯用异常

Crates.io Version docs.rs

通过无缝使用异常进行错误传播,加快基于 Result 的函数“快乐路径”的速度。

快速入门

#[iex] 应用到所有返回 Result 的函数上,使其返回一个高效可传播的 #[iex] Result,就像通常一样使用 ?,偶尔需要真正的 Result 时调用 .into_result()。这是非常直观的。

与代数 Result 相比,#[iex] Result 是非对称的:它牺牲了错误处理性能,作为回报

  • 消除了快乐路径中的分支
  • 通过从不显式存储错误或枚举区分符来减少内存使用
  • 使编译器能够在将小对象包裹在 Ok 中时使用寄存器而不是内存
  • 在机器码中清晰地分离快乐和不快乐路径,从而实现更好的指令局部性

基准测试

为了演示,我们将 serdeserde_json 进行了重写,以在反序列化路径中使用 #[iex],并使用 Rust JSON 基准测试 来比较性能。以下是结果

速度(MB/s) 加拿大 citm_catalog twitter
DOM 结构体 DOM 结构体 DOM 结构体
结果 296.2 439.0 392.4 876.8 274.8 536.4
#[iex] 结果 294.8 537.0 400.6 940.6 303.8 568.8
性能提升 -0.5% +22% +2% +7% +11% +6%

数据是在5次运行中平均得出的。数据复制的存储库已发布在 GitHub 上。

示例

use iex::{iex, Outcome};

#[iex]
fn checked_divide(a: u32, b: u32) -> Result<u32, &'static str> {
    if b == 0 {
        // Actually raises a custom panic
        Err("Cannot divide by zero")
    } else {
        // Actually returns a / b directly
        Ok(a / b)
    }
}

#[iex]
fn checked_divide_by_many_numbers(a: u32, bs: &[u32]) -> Result<Vec<u32>, &'static str> {
    let mut results = Vec::new();
    for &b in bs {
        // Actually lets the panic bubble
        results.push(checked_divide(a, b)?);
    }
    Ok(results)
}

fn main() {
    // Actually catches the panic
    let result = checked_divide_by_many_numbers(5, &[1, 2, 3, 0]).into_result();
    assert_eq!(result, Err("Cannot divide by zero"));
}

依赖项

~0.6–1MB
~24K SLoC