简体   繁体   English

为什么 Rust 中的枚举值绑定这么慢?

[英]Why enum value binding in Rust is so slow?

I am currently learning Rust because I wanted to use it in project that requires a very high performance.我目前正在学习 Rust,因为我想在需要非常高性能的项目中使用它。 I initially fallen in love with enums but then I started to evaluate their performance and I have found something that is really boggling me.我最初爱上了枚举,但后来我开始评估它们的性能,我发现了一些让我难以置信的东西。 Here is an example:这是一个例子:

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

Results I get:我得到的结果:

enum without fields func call sum: 10000000 at 100ns
enum with field func call sum: 10000000 at 6.3425ms

eval function should execute exactly the same instructions as eval2 for V1 enum but it's working about 60x slower. eval function 应该执行与用于 V1 枚举的 eval2 完全相同的指令,但它的工作速度慢了大约 60 倍。 Why is this happening?为什么会这样?

Viewing the assembly, your first loop is optimized entirely into a single mov 10000000 instruction (that is, the compiler does something equivalent to sum += EXAMPLES ) while the second is not.查看程序集,您的第一个循环完全优化为单个mov 10000000指令(即,编译器执行与sum += EXAMPLES等效的操作),而第二个则不是。 I do not know why the second loop is not constant-optimized as heavily.我不知道为什么第二个循环没有进行大量的持续优化。

I see no difference in performance, as one would expect.正如人们所期望的那样,我认为性能没有差异。

$ ./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

One problem might be the use of simple "wall clock" time for benchmarking.一个问题可能是使用简单的“挂钟”时间进行基准测试。 This simple count of how much time passed is vulnerable to anything else running which might consume resources.这个简单的时间计算很容易受到任何可能消耗资源的运行的影响。 Anti-virus, a web browser, any program.防病毒,web 浏览器,任何程序。 Instead, use benchmark tests .相反,使用基准测试

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM