cargo test --release 导致堆栈溢出。为什么没有货台?

cargo test --release causes a stack overflow. Why doesn't cargo bench?

在尝试编写优化的 DSP 算法时,我想知道堆栈分配和堆分配之间的相对速度,以及堆栈分配数组的大小限制。我知道有一个堆栈帧大小限制,但我不明白为什么下面的 运行s,用 cargo bench 生成看似真实的基准测试结果,但在 运行 时因堆栈溢出而失败cargo test --release.

#![feature(test)]
extern crate test;

#[cfg(test)]
mod tests {
    use test::Bencher;

    #[bench]
    fn it_works(b: &mut Bencher) {
        b.iter(|| { let stack = [[[0.0; 2]; 512]; 512]; });
    }
}

为了正确看待事情,请注意数组的大小为 8 × 2 × 512 × 512 = 4 MiB。

cargo test 崩溃但 cargo bench 没有,因为 "test" 在新线程 中调用函数 it_works() ,而 "bench" 在主线程 中调用它

主线程的默认堆栈大小通常为 8 MiB,因此该数组将占用可用堆栈的一半。很多,但仍有可用空间,因此基准 运行 正常。

stack size of a new thread, however, is typically much smaller. On Linux it is 2 MiB, and other platforms could be even smaller。因此,您的 4 MiB 数组很容易溢出线程的堆栈并导致堆栈溢出/段错误。

您可以将新线程的默认堆栈大小增加

$ RUST_MIN_STACK=8388608 cargo test 

cargo test 运行 在并行线程中进行测试以缩短总测试时间,而基准测试在同一线程中按顺序 运行 以减少噪音。

由于堆栈大小有限,将此数组分配到堆栈上不是一个好主意。您必须将它存储在堆上(box 它)或作为全局 static mut.