2017-04-05 20 views
2

コード内の機能ゲートの後ろにパフォーマンスに影響を及ぼす関数呼び出しをいくつか入れたいと思います。機能が有効になっていない場合、代わりにその機能の実装が空の状態になっていることを考えていました。そうすれば、欲しいことに、Rustコンパイラは機能から完全に削除することができます。このような空の関数はRustで最適化されますか?

何か:それが空の場合、fooへの呼び出しは()離れ

// Included if feature is enabled 
fn foo() { 
    // ... 
} 

// Included if the feature is disabled 
fn foo() {} 

// Performance critical code 
for i in 1..1000000000 { 
    // ... 
    foo(); 
} 

を最適化しますか?

答えて

6

だけでそれを試してみてください素晴らしいCompiler Explorer :)

例の結果アセンブリは次のとおりです。

example::main: 
    push rbp 
    mov  rbp, rsp 
    mov  eax, 1 
.LBB0_1: 
    xor  ecx, ecx 
    cmp  eax, 1000000000 
    setl cl 
    add  ecx, eax 
    cmp  eax, 1000000000 
    mov  eax, ecx 
    jl  .LBB0_1 
    pop  rbp 
    ret 

ご覧のとおり、call命令はありません。foo()はまったく呼び出されません。しかし、外界に影響を与えないので、なぜループが削除されないのか疑問に思うかもしれません。私はちょうどそれらのループが実際にある意味で時間を無駄にするのに使用されていると仮定することができます。カウンターを100に減らすと、ループは完全に削除されます。とにかく

はい、オプティマイザは、空の機能を削除します!

+0

ループ自体がなぜ削除されないのか、私はそれを言及してくれたことに感謝しました。多分誰かがこの行動を説明することができます。 – ljedrz

+2

このループの動作は本当に奇妙です(特に100のしきい値)。 Clangを使うと、これらのループは完全に削除されているので、LLVMはRustでも実行できると思うでしょうが、私はそれを引き起こすようには見えません:x –

+0

@MatthieuMループは 'let mut i = 1_000_000_000;で最適化されています。一方、i> 0 {foo(); i - = 1;} ' – ArtemGr

1

現在の安定錆のリリースモードでの私のチェックによると、次のコード:ループが空であるかのように

fn foo() {} 


fn main() { 
    for _ in 1..1000000000 { 
     foo(); 
    } 

    println!(); // a side effect so that the whole program is not optimized away 
} 

は同じアセンブリにコンパイル:

for _ in 1..1000000000 {} 
関連する問題