27

スニペットを検討してください

struct Foo {
    dummy: [u8; 65536],
}

fn bar(foo: Foo) {
    println!("{:p}", &foo)
}

fn main() {
    let o = Foo { dummy: [42u8; 65536] };
    println!("{:p}", &o);
    bar(o);
}

プログラムの典型的な結果

0x7fffc1239890
0x7fffc1229890

住所が違うところ。

どうやら、dummyコンパイラの move 実装で予想されるように、大きな配列がコピーされています。dummy残念ながら、非常に大きな配列と同様に、これはパフォーマンスに重大な影響を与える可能性があります。この影響により、関数が実際に引数を概念的に「消費」している場合でも、人々は代わりに参照による引数の受け渡しを選択することを余儀なくされる可能性があります。

Fooは を導出しないため、Copyオブジェクトoが移動されます。Rust は移動されたオブジェクトへのアクセスを禁止しているためbar、元のオブジェクトの「再利用」を妨げているものは何oですか? 根本的な問題はありますか、それともコンパイラがこのビット単位のコピーを最適化する日が来るのでしょうか?

4

1 に答える 1

26

Rust では (C や C++ とは異なり) 値のアドレスが重要であるとは見なされないことを考えると、コピーの省略を防ぐ言語の観点からは何もありません。

ただし、現在、rustc は何も最適化しません。すべての最適化は LLVM に委譲されており、ここで LLVM オプティマイザの制限に達したようです (この制限が LLVM が C のセマンティクスに近いためなのか、単に省略されているためなのかは不明です)。 .

このため、コード生成を改善するには 2 つの方法があります。

  • この最適化を実行するように LLVM に教える (可能であれば)
  • この最適化を実行するようにrustcに教えます(最適化パスは、MIRを備えたrustcに来ています)

しかし今のところ、そのような大きなオブジェクトがスタックに割り当てられるのを避けたいだけかもしれませんBox。たとえば、そうすることができます。

于 2016-07-25T15:19:00.153 に答える