Nugine 的个人博客关于

Rust 消除 panic 代码膨胀

Rust 提供了一个不稳定功能 panic_immediate_abort,在 panic 时立即终止进程,以这种方式编译可以消除相当一部分代码膨胀。

用 cargo 新建项目,测试名称是 remove_panic

cargo new --lib remove_panic

测试函数

pub fn init_data(slice: &mut [usize]) {
    let s = &mut slice[..6];
    s[0] = 4;
    s[1] = 4;
    s[2] = 5;
    s[3] = 6;
    s[4] = 7;
    s[5] = 5;
}

以 release 模式编译

cargo build --release

用 cargo asm 工具查看汇编

cargo asm -- remove_panic::init_data

此时函数中包含 panic 相关代码。

我们用 panic_immediate_abort 参数编译

cargo +nightly \
    -Z build-std=std,panic_abort \
    -Z build-std-features=panic_immediate_abort \
    build --release \
    --target x86_64-unknown-linux-gnu  

找到目标文件,用 rust-objdump 工具将汇编输出到文本文件

cd target/x86_64-unknown-linux-gnu/release/
rust-objdump --demangle --disassemble-all libremove_panic.rlib > out

在文本文件中搜素 init_data 符号,找到函数

函数中的 panic 相关代码已被移除,替换成 ud2,以 CPU 非法指令异常让进程终止。这种优化在 wasm、嵌入式代码中也适用。

总结,目前 Rust 有三种 panic 策略:

  • unwind:运行 panic 钩子,进行异常展开。提供异常恢复。
  • abort:运行panic 钩子,终止
  • immediate_abort:立即终止(不稳定功能)

使用不同策略编译可能会得到不同的程序行为和代码体积。

发布于 2022-03-10地址: GitHub, 知乎