为什么 Rust 中的枚举值绑定如此之慢?

Ada*_*ski 2 performance enums rust

我目前正在学习 Rust,因为我想在需要非常高性能的项目中使用它。我最初爱上了枚举,但后来我开始评估它们的性能,我发现了一些让我感到难以置信的东西。下面是一个例子:

use std::time::{Instant};

pub enum MyEnum<'a> {
    V1,
    V2(&'a MyEnum<'a>),
    V3,
}

impl MyEnum<'_> {
    pub fn eval(&self) -> i64 {
        match self {
            MyEnum::V1 => 1,
            MyEnum::V2(_) => 2,
            MyEnum::V3 => 3,
        }
    }
    pub fn eval2(&self) -> i64 {
        match self {
            MyEnum::V1 => 1,
            MyEnum::V2(a) => a.eval2(),
            MyEnum::V3 => 3,
        }
    }
}


fn main() {
    const EXAMPLES: usize = 10000000;
    let en = MyEnum::V1{};

    let start = Instant::now();
    let mut sum = 0;
    for _ in 0..EXAMPLES {
        sum += en.eval()
    }
    println!("enum without fields func call sum: {} at {:?}", sum, start.elapsed());

    let start = Instant::now();
    let mut sum = 0;
    for _ in 0..EXAMPLES {
        sum += en.eval2()
    }
    println!("enum with field func call sum: {} at {:?}", sum, start.elapsed());
}
Run Code Online (Sandbox Code Playgroud)

我得到的结果:

enum without fields func call sum: 10000000 at 100ns
enum with field func call sum: 10000000 at 6.3425ms
Run Code Online (Sandbox Code Playgroud)

对于 V1 枚举,eval 函数应该执行与 eval2 完全相同的指令,但它的运行速度要慢 60 倍。为什么会这样?

kmd*_*eko 5

查看程序集,您的第一个循环被完全优化为一条mov 10000000指令(即​​,编译器执行与 等效的操作sum += EXAMPLES),而第二个循环则不是。我不知道为什么第二个循环没有进行大量的常量优化。