Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

ループとイテレータにおけるパフォーマンス

ループとイテレータのどちらを使うべきかを判断するには、どちらの 実装がより高速なのかを知る必要があります。つまり、明示的な for ループを使った search 関数のバージョンと、イテレータを使った バージョンのどちらが速いかです。

私たちは、アーサー・コナン・ドイル卿の シャーロック・ホームズの冒険 の 全文を String に読み込み、その内容の中から単語 the を探すことで ベンチマークを実行しました。for ループを使う search のバージョンと、 イテレータを使うバージョンでのベンチマーク結果は次のとおりです。

test bench_search_for  ... bench:  19,620,300 ns/iter (+/- 915,700)
test bench_search_iter ... bench:  19,234,900 ns/iter (+/- 657,200)

2 つの実装のパフォーマンスはほぼ同じです!ここではベンチマーク コードの説明はしません。というのも、要点は 2 つのバージョンが等価で あることを証明することではなく、これら 2 つの実装のパフォーマンスが おおむねどのように比較されるかの感覚をつかむことだからです。

より包括的なベンチマークを行うには、contents としてさまざまなサイズの さまざまなテキストを使い、query として異なる単語や長さの異なる単語を 使い、そのほかあらゆる種類の変化を試すべきです。要点は次のとおりです。 イテレータは高水準の抽象化ではありますが、コンパイルされると、あたかも 自分でより低水準のコードを書いたかのような、ほぼ同じコードになります。 イテレータは Rust の ゼロコスト抽象化 の 1 つであり、これはその抽象化を 使っても実行時オーバーヘッドが一切追加されないことを意味します。これは、 C++ の元の設計者であり実装者である Bjarne Stroustrup が、2012 年の ETAPS 基調講演「Foundations of C++」でゼロオーバーヘッドを次のように定義して いることに対応しています。

一般に、C++ の実装はゼロオーバーヘッドの原則に従います。使わないものに 対しては、コストを支払う必要はありません。さらに、使うものについても、 手書きでそれ以上に良くコード化することはできません。

多くの場合、イテレータを使った Rust コードは、自分で手書きするのと同じ アセンブリにコンパイルされます。ループ展開や配列アクセス時の境界チェックの 除去といった最適化が適用され、その結果のコードは非常に効率的になります。 これでこのことがわかったので、恐れることなくイテレータやクロージャを使う ことができます。これらを使うとコードはより高水準に見えますが、そのための 実行時パフォーマンスのペナルティは課されません。

まとめ

クロージャとイテレータは、関数型プログラミング言語の考え方に着想を得た Rust の機能です。これらは、高水準の考え方を低水準のパフォーマンスで明確に 表現する Rust の能力に貢献しています。クロージャとイテレータの実装は、 実行時パフォーマンスに影響を与えないようになっています。これは、ゼロコスト 抽象化を提供することを目指す Rust の目標の一部です。

I/O プロジェクトの表現力を改善したところで、次は cargo のさらにいくつかの 機能を見ていきましょう。これらは、このプロジェクトを世界と共有するのに 役立ちます。