1. ホーム
  2. c++

[解決済み] C++のExceptionは本当に遅いのか?

2022-10-15 07:30:18

質問

私が見ていたのは C++における体系的なエラー処理-Andrei Alexandrescu を見ていて、C++ の例外処理は非常に遅いと言っています。

これは C++98 ではまだ真実なのでしょうか?

どのように解決するのですか?

例外に対して現在主に使用されているモデル (Itanium ABI、VC++ 64 ビット) は、ゼロコスト モデル例外です。

このアイデアは、ガードを設定し、例外の存在をどこでも明示的にチェックすることによって時間を失う代わりに、コンパイラーは例外をスローする可能性のある任意のポイント (プログラム カウンター) をハンドラーのリストにマップするサイド テーブルを生成するというものです。例外が投げられると、このリストが正しいハンドラを選ぶために参照され(もしあれば)、スタックが巻き戻されます。

典型的な if (error) の戦略に比べて

  • ゼロコストモデルは、その名の通り、例外が発生しない場合は無料です。
  • 10倍/20倍程度のコストがかかる if 例外が発生した場合

しかし、そのコストは些細なことで測れるものではありません。

  • サイドテーブルは一般に 冷たい であり、したがってメモリからそれをフェッチするのは長い時間がかかります。
  • 正しいハンドラを決定するには、RTTIが必要です。メモリ上に散在する多くのRTTIディスクリプタをフェッチし、複雑なオペレーションを実行します(基本的に dynamic_cast テスト)

つまり、ほとんどがキャッシュミスであり、純粋なCPUコードと比較すると些細なことではありません。

注: より詳細については TR18015報告書 5.4章 例外処理 (pdf)

だから、そう、例外は遅いのです 例外パスで となりますが、それ以外は明示的なチェック( if 戦略)よりも速いです。

注: Andrei Alexandrescu は、この「より速く」という言葉に疑問を抱いているようです。私自身は、あるプログラムは例外を使用してより速く、別のプログラムは分岐を使用してより速くというように、物事が両方向に振れるのを見てきましたので、確かに特定の条件では最適化の損失があるようです。


それは重要ですか?

私は関係ないと主張します。プログラムは 読みやすさ を念頭に置いて書かれるべきであり、パフォーマンスではありません(少なくとも、第一の基準ではありません)。例外は、呼び出し元が失敗をその場で処理できない、あるいは処理したくないと予想される場合に使用され、スタック上に渡されます。 ボーナス: C++11 では、標準ライブラリを使用してスレッド間で例外をマーシャルすることができます。

これは微妙ですが、私が主張しているのは map::find は投げるべきではないと主張していますが、私は map::find を返すのは問題ありません。 checked_ptr を返し、それが NULL であるために参照解除に失敗した場合は throw します。後者の場合は、Alexandrescu が紹介したクラスの場合と同じです。 を選択します。 後者の場合、Alexandrescuが紹介したクラスのように、呼び出し側は明示的なチェックと例外に依存することのどちらかを選択します。呼び出し側により多くの責任を与えることなく権限を与えることは、通常、良い設計のしるしです。