2017-05-25 43 views
1

我有一些代码,我经常使用unwrap()模式下,我可以肯定它不会恐慌。其中一些片断处于性能关键功能,所以我想知道是否应该删除这些unwrap()以支持未经检查的适用函数变体。但是,我没有看到与#[bench]测试有任何区别,并且这两个变体的ASM看起来与我很相似(尽管我不是专家)。是否在优化模式下展开()?

看来Rust能够优化这种情况;我是对的还是应该使用未经检查的功能而不是unwrap()

MCVE:

use self::Foo::*; 
use self::Error::*; 

#[derive(Debug)] 
enum Foo { 
    Bar(Box<Foo>), 
    Baz 
} 

#[derive(Debug)] 
enum Error { 
    NotBar 
} 

impl Foo { 
    fn bar_mut_ref(&mut self) -> Result<&mut Foo, Error> { 
     match *self { 
      Bar(ref mut foo) => Ok(foo), 
      _ => Err(NotBar) 
     } 
    } 

    fn bar_mut_ref_unchecked(&mut self) -> &mut Foo { 
     match *self { 
      Bar(ref mut foo) => foo, 
      _ => panic!("bar_mut_ref_unchecked() called on a non-Bar!") 
     } 
    } 

    fn bazify(&mut self) { 
     match *self { 
      Bar(_) => { *self = Baz }, 
      _ =>() 
     } 
    } 
} 

fn do_stuff_with_foo(foo: &mut Foo) { 
    match *foo { 
     Bar(_) => { 
      foo.bar_mut_ref().unwrap().bazify(); // is _unchecked() better here? 
      // underscore was used because foo is assigned to a new value here 
     }, 
     _ => {} 
    } 
} 

fn main() { 
    let mut foo = Bar(Box::new(Bar(Box::new(Baz)))); 
    do_stuff_with_foo(&mut foo); 
    println!("{:?}", foo); 
} 
+2

至于所有的微观优化问题:如果这不是问题,请使用安全的替代方案。 –

+0

@ildjarn:我在[Rust playground](https://play.rust-lang.org)上做了检查。我可以看到,您链接的ASM是用一组特定的标志编译的,以将其大小减小到功能最小值;这非常方便。 – ljedrz

+0

@MatthieuM .:这很有道理,但在这种情况下,两种变体都是同样安全的。 – ljedrz

回答

1

这两种方法的A more direct comparison产生相同ASM,所以至少对于这个简单的例子中,答案似乎是:是,这种情况下可被优化了。

example::do_stuff_with_foo: 
     push rbp 
     mov  rbp, rsp 
     push rbx 
     push rax 
     mov  rbx, qword ptr [rdi] 
     test rbx, rbx 
     je  .LBB1_3 
     cmp  qword ptr [rbx], 0 
     je  .LBB1_3 
     mov  rdi, rbx 
     call core::ptr::drop_in_place 
     mov  qword ptr [rbx], 0 
.LBB1_3: 
     add  rsp, 8 
     pop  rbx 
     pop  rbp 
     ret 
+0

社区Wiki不会使链接答案可接受。我会亲自建议发布一个常规答案,并可能列出发布的程序集,说明两种情况都会产生它。 –

+0

@MatthieuM。 :随意按照你认为更合适的格式编辑答案 - 这就是为什么它是CW。 ; - ] – ildjarn