2011-02-04 26 views
18

リアルタイムアプリケーションで仮想継承を使用することを検討しています。仮想継承を使用すると、仮想関数を呼び出す場合と同様のパフォーマンスへの影響がありますか?問題のオブジェクトは起動時にのみ作成されますが、階層からのすべての関数がvtableを介して送出されるか、または仮想基本クラスからの関数のみが送出されるかどうかが関係します。仮想継承のパフォーマンスへの影響

+1

増加する可能性があり、仮想継承を使用する必要は本当にありません。 –

+0

@ ZacHowland、あなたがGoogle Testでモックを使用している場合を除きます。 (gtest) –

+3

@Amigable:「ない」はありません。 Google Testを使用している場合でも、複数の継承を処理する場合には仮想継承のみを使用します。 –

答えて

22

一般的な実装では、データメンバーの仮想基本クラスへのアクセスが追加の間接参照を使用します。

Jamesがコメントで指摘しているように、多重継承シナリオで基本クラスのメンバ関数を呼び出すにはthisポインタの調整が必要であり、その基本クラスが仮想の場合、基本クラスのサブセットのオフセットは、派生クラスのオブジェクト内のオブジェクトは、派生クラスの動的型に依存し、実行時に計算する必要があります。

これは実際のアプリケーション上の任意の目に見えるパフォーマンスへの影響は、多くのものに依存しているかどうか:

  • ない仮想拠点データメンバー全く持って?多くの場合、それは事実上派生する必要がある抽象基底クラスであり、抽象的な基底にはデータ・メンバーがあるとしばしばコードの匂いがしばしばあります。

  • ものはクリティカルパスににアクセスし、データ・メンバーと仮想拠点を持っていると仮定?ユーザーがGUIでいくつかのボタンをクリックすると、数十の追加の回帰があり、誰も気づかないでしょう。

  • 何だろう代替仮想塩基が回避されている場合は?デザインが劣っているだけでなく、代替デザインもパフォーマンスに影響を与える可能性があります。結局のところ、TANSTAAFLと同じ目標を達成する必要があります。それから、あなたはもう一つのパフォーマンス損失と、劣悪なデザインを交換しました。


追加注:かなり徹底的に、このような質問に答えるスタン・リップマンのInside the C++ Object Model、を見てください。

+0

明確にするために、仮想基底クラスメンバー/関数への呼び出しだけが間接的に追加されますか? – Graeme

+0

@Graeme:私は確かにこの分野の専門家ではありませんが、仮想基底クラスメンバ_functions_への呼び出しがどのようにパフォーマンスの低下につながるかはわかりません。それらは静的に( 'B :: f()')、または非仮想ベースのメンバ関数と同様に、派生クラスの仮想テーブルを介して動的に送出されます。 ICBWT。 – sbi

+1

@sbi:関数が仮想でない場合、呼び出される関数を静的に選択することができますが、実行時に 'this'ポインタを計算する必要がありますか? –

0

本当に仮想継承を意味していますか?そうであれば、それは通常の仮想関数呼び出しのコストと同じです。 vtableの連鎖検索は、指定されたパスの直後にあります。

あなたはこれが起動時であると言いました。あなたのディスクのオーバーヘッド(あなたのコードをメモリにロードするだけです)では、vtable検索のために半ダース程度の指示以上の時間が必要です。私はあなたがこれをプロファイリングして差異を検出することができれば多少驚くかもしれません。

3

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.735%を費やしていることを示しています。プログラムの "すべての仮想" バージョンの場合、中間オーバーヘッドは 13.7%(命令の13%)に上昇します。仮想関数テーブル実装の「サンク」変種 は、 標準実装に対して、 のオーバーヘッドを中央値で21%減らします。将来のプロセッサでは、これらの オーバーヘッドはあなたが多重継承を使用している場合を除き、適度

http://www.cs.ucsb.edu/~urs/oocsb/papers/oopsla96.pdf

+1

+1を参考にしてください。 –

+4

コンパイラの最適化によってこの研究が廃止された場合、私は驚くことはありません。 1996年に発行されました。 –

+6

郵便番号。しかし疑問は___仮想関数___についてではなく、___仮想継承___に関するものでした。 – sbi

関連する問題