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

プロファイリング

プログラムを最適化するときは、プログラムのどの部分が「ホット」(実行時性能に影響するほど頻繁に実行される)であり、変更する価値があるのかを判断する方法も必要です。これはプロファイリングによって行うのが最適です。

プロファイラー

利用可能なプロファイラーは数多くあり、それぞれに長所と短所があります。以下は、Rust プログラムで正常に使用されてきたプロファイラーの不完全な一覧です。

  • perf は、ハードウェアパフォーマンスカウンターを使用する汎用プロファイラーです。 HotspotFirefox Profiler は、perf によって記録されたデータを表示するのに適しています。 Linux で動作します。
  • Instruments は、macOS の Xcode に付属する汎用プロファイラーです。
  • Intel VTune Profiler は汎用プロファイラーです。Windows、Linux、macOS で動作します。
  • AMD μProf は汎用プロファイラーです。Windows と Linux で動作します。
  • samply は、Firefox Profiler で表示できるプロファイルを生成するサンプリングプロファイラーです。 Mac、Linux、Windows で動作します。
  • flamegraph は、perf/DTrace を使用してコードをプロファイリングし、その結果をフレームグラフで表示する Cargo コマンドです。Linux と、DTrace をサポートするすべてのプラットフォーム(macOS、FreeBSD、NetBSD、および場合によっては Windows)で動作します。
  • CachegrindCallgrind は、グローバル単位、関数単位、ソース行単位の命令数、およびシミュレートされたキャッシュと分岐予測のデータを提供します。Linux と一部の他の Unix で動作します。
  • DHAT は、コードのどの部分が多数のアロケーションを引き起こしているかを見つけるのに適しており、ピークメモリ使用量に関する洞察を得るのにも役立ちます。また、memcpy へのホットな呼び出しを特定するためにも使用できます。Linux と一部の他の Unix で動作します。dhat-rs は実験的な代替手段であり、少し機能は弱く、Rust プログラムに小さな変更が必要ですが、すべてのプラットフォームで動作します。
  • heaptrackbytehound はヒーププロファイリングツールです。Linux で動作します。
  • counts はアドホックなプロファイリングをサポートしており、eprintln! 文の使用と頻度ベースの後処理を組み合わせます。これは、コードの一部についてドメイン固有の洞察を得るのに適しています。すべてのプラットフォームで動作します。
  • Coz は、最適化の可能性を測定するために因果プロファイリングを実行し、coz-rs を通じて Rust をサポートしています。Linux で動作します。

デバッグ情報

リリースビルドを効果的にプロファイリングするには、ソース行のデバッグ情報を有効にする必要がある場合があります。これを行うには、Cargo.toml ファイルに次の行を追加します。

[profile.release]
debug = "line-tables-only"

debug 設定の詳細については、Cargo documentation を参照してください。

残念ながら、上記の手順を実行しても、標準ライブラリコードに関する詳細なプロファイリング情報は得られません。これは、配布されている Rust 標準ライブラリのバージョンがデバッグ情報付きでビルドされていないためです。

これを回避する最も信頼できる方法は、these instructions に従って独自のコンパイラーと標準ライブラリをビルドし、リポジトリルートの bootstrap.toml ファイルに次の行を追加することです。

[rust]
debuginfo-level = 1

これは手間がかかりますが、場合によってはその労力に見合うことがあります。

あるいは、不安定な build-std 機能を使用すると、プログラムの通常のコンパイルの一部として、同じビルド設定で標準ライブラリをコンパイルできます。ただし、標準ライブラリのデバッグ情報に含まれるファイル名はソースコードファイルを指しません。これは、この機能が標準ライブラリのソースコードもダウンロードするわけではないためです。そのため、この方法は、完全に動作するためにソースコードを必要とする Cachegrind や samply などのプロファイラーには役立ちません。

フレームポインター

Rust コンパイラーはフレームポインターを最適化で取り除く場合があり、これによりスタックトレースなどのプロファイリング情報の品質が低下することがあります。コンパイラーにフレームポインターを使用させるには、-C force-frame-pointers=yes フラグを使用します。例:

RUSTFLAGS="-C force-frame-pointers=yes" cargo build --release

あるいは、(1 つ以上のプロジェクトに対して)config.toml ファイルからフレームポインターの使用を強制するには、次の行を追加します。

[build]
rustflags = ["-C", "force-frame-pointers=yes"]

シンボルのデマングリング

Rust は、コンパイル済みコード内で関数名をエンコードするために、名前マングリングの一形式を使用します。プロファイラーがこれを認識していない場合、その出力には _ZN3foo3barE_ZN28_$u7b$$u7b$closure$u7d$$u7d$E、または _RMCsno73SFvQKx_1cINtB0_3StrKRe616263_E のように、_ZN または _R で始まるシンボル名が含まれることがあります。

このような名前は、rustfilt を使用して手動でデマングルできます。

プロファイリング中にシンボルのデマングリングで問題が発生している場合は、mangling format をデフォルトのレガシー形式から新しい v0 形式に変更する価値があるかもしれません。

コマンドラインから v0 形式を使用するには、-C symbol-mangling-version=v0 フラグを使用します。例:

RUSTFLAGS="-C symbol-mangling-version=v0" cargo build --release

あるいは、(1 つ以上のプロジェクトに対して)config.toml ファイルからこれらの命令を要求するには、次の行を追加します。

[build]
rustflags = ["-C", "symbol-mangling-version=v0"]