Performance Rust中的枚举值绑定为何如此缓慢?

Performance Rust中的枚举值绑定为何如此缓慢?,performance,enums,rust,Performance,Enums,Rust,我目前正在学习Rust,因为我想在需要非常高性能的项目中使用它。最初我爱上了Enum,但后来我开始评估它们的性能,我发现了一些让我难以置信的东西。以下是一个例子: use std::time::{Instant}; pub enum MyEnum<'a> { V1, V2(&'a MyEnum<'a>), V3, } impl MyEnum<'_> { pub fn eval(&self) -> i64

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

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());
}

eval函数应该执行与v1enum的eval2完全相同的指令,但它的工作速度要慢60倍。为什么会发生这种情况?

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

我看不到性能上的差异

$ ./test
enum without fields func call sum: 10000000 at 307.543596ms
enum with field func call sum: 10000000 at 312.196195ms

$ rustc --version
rustc 1.43.1 (8d69840ab 2020-05-04)

$ uname -a
Darwin Windhund.local 18.7.0 Darwin Kernel Version 18.7.0: Mon Feb 10 21:08:45 PST 2020; root:xnu-4903.278.28~1/RELEASE_X86_64 x86_64 i386 MacBookPro15,2 Darwin

一个问题可能是使用简单的“挂钟”时间进行基准测试。这一简单的计算所花费的时间容易受到任何其他可能消耗资源的运行的影响。防病毒,网络浏览器,任何程序。相反,请使用。

欢迎使用堆栈溢出!很难回答你的问题,因为它没有包含一个。我们无法确切地告诉您如何运行此代码。请将您的问题包括在附加信息中。谢谢另外,第二个函数执行递归调用,这与第一个函数完全不同。为什么您认为这些应该是相同的呢?第一个函数很可能优化为
返回discriminant+1。第二个函数需要一个分支。此外,在第一个函数中,编译器内联函数调用,并且足够聪明,可以将循环转换为单个
sum+=EXAMPLES
。提示:100ns中1000万次循环迭代应该会告诉您,考虑到单个cpu周期约为1/3纳秒,基准测试有点不正确。
$ ./test
enum without fields func call sum: 10000000 at 307.543596ms
enum with field func call sum: 10000000 at 312.196195ms

$ rustc --version
rustc 1.43.1 (8d69840ab 2020-05-04)

$ uname -a
Darwin Windhund.local 18.7.0 Darwin Kernel Version 18.7.0: Mon Feb 10 21:08:45 PST 2020; root:xnu-4903.278.28~1/RELEASE_X86_64 x86_64 i386 MacBookPro15,2 Darwin