简体   繁体   中英

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. 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. 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. 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. Instead, use benchmark tests .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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