2017-05-25 45 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