リアルタイムアプリケーションで仮想継承を使用することを検討しています。仮想継承を使用すると、仮想関数を呼び出す場合と同様のパフォーマンスへの影響がありますか?問題のオブジェクトは起動時にのみ作成されますが、階層のすべての関数がvtableを介してディスパッチされるのか、仮想基本クラスの関数のみがディスパッチされるのかが心配です。
4 に答える
一般的な実装では、仮想基本クラスのデータメンバーへのアクセスに追加の間接参照を使用します。
Jamesがコメントで指摘しているように、多重継承シナリオで基本クラスのメンバー関数を呼び出すには、this
ポインターを調整する必要があります。その基本クラスが仮想の場合、派生クラスの基本クラスサブオブジェクトのオフセットオブジェクトは派生クラスの動的タイプに依存し、実行時に計算する必要があります。
これが実際のアプリケーションに目に見えるパフォーマンスの影響を与えるかどうかは、多くのことに依存します。
仮想ベースにはデータメンバーがありますか?多くの場合、仮想的に派生する必要があるのは抽象ベースクラスであり、データメンバーを持つ抽象ベースは、とにかくコードの臭いであることがよくあります。
データメンバーを含む仮想ベースがあると仮定すると、それらはクリティカルパスでアクセスされますか?ユーザーがGUIのいくつかのボタンをクリックすると、さらに数十の間接化が発生した場合、誰も気付かないでしょう。
仮想ベースが回避された場合の代替手段は何でしょうか?設計が劣っているだけでなく、代替設計もパフォーマンスに影響を与える可能性があります。結局のところ、それは同じ目標を達成する必要があります、そしてTANSTAAFL。次に、あるパフォーマンスの低下を別のパフォーマンスの低下と劣った設計と交換しました。
追記:StanLippmannのInsidethe C ++ Object Modelをご覧ください。これは、このような質問に完全に答えます。
OOPSLA'96で公開された次の大規模な実験的研究をご覧ください。私はbibtexエントリ、要約、および論文へのリンクをコピーして貼り付けています。これは、これまでのトピックに関する最も包括的な実験的研究だと思います。
@article{driesen1996direct,
title={{The direct cost of virtual function calls in C++}},
author={Driesen, K. and H{\\"o}lzle, U.},
journal={ACM Sigplan Notices},
volume={31},
number={10},
pages={306--323},
issn={0362-1340},
year={1996},
publisher={ACM}
}
要約: 仮想関数テーブルを使用した標準実装を想定して、C++プログラムでの仮想関数呼び出しの直接コストを調査します。実行可能検査とプロセッサシミュレーションの組み合わせを使用して、多数の大規模なベンチマークプログラムについてこのオーバーヘッドを実験的に測定します。私たちの結果は、測定されたC ++プログラムが、時間の中央値5.2%、命令の3.7%をディスパッチコードに費やしていることを示しています。プログラムの「すべての仮想」バージョンの場合、オーバーヘッドの中央値は13.7%(命令の13%)に上昇します。仮想関数テーブルの実装の「サンク」バリアントは、標準の実装と比較して、オーバーヘッドを中央値で21%削減します。将来のプロセッサでは、これらのオーバーヘッドは適度に増加する可能性があります
仮想継承を意味しますか?その場合、通常の仮想関数呼び出しのコストと同じです。vtableチェーン検索は、指定されたパスをたどります。
これは起動時だとおっしゃいました。ディスクのオーバーヘッド(単にコードをメモリにロードすることによる)は、vtableルックアップの場合、半ダースほどの命令よりも桁違いに多くの時間を必要とする可能性があります。これをプロファイリングして違いを検出できたら、私は少し驚かれることでしょう。
GNU C ++ 17を使用した私のテストに基づいて、コンパイルまたはランタイムの詳細を検査せずに、仮想基本クラスのデータメンバーにアクセスしてもパフォーマンスに影響はありません。