4

私はCで仮想マシンを作成しました。この仮想マシンには、VMのオペコードの機能を提供する関数へのポインターが入力された呼び出しテーブルがあります。仮想マシンが実行されると、最初にプログラムが解釈され、提供されたオペコードの呼び出しテーブルに適切な関数に対応するインデックスの配列が作成されます。次に、配列をループして、最後に到達するまで各関数を呼び出します。

各命令は非常に小さく、通常は1行です。インライン化に最適です。問題は、実行時に決定されるため、コンパイラが仮想マシンの命令がいつ呼び出されるかを認識しないため、それらをインライン化できないことです。関数呼び出しと引数の受け渡しのオーバーヘッドにより、VMのパフォーマンスが低下しています。これを回避する方法について何かアイデアはありますか?

4

2 に答える 2

5

オーバーヘッドを削減するためのいくつかのオプションは次のとおりです。

  1. 関数を(または同様のものとして)宣言してfastcall、引数の受け渡しのオーバーヘッドを削減します
  2. 関数ポインターのテーブルの代わりに大きなswitch-caseを使用します(コンパイラーはジャンプテーブルに最適化され、実際に関数を呼び出すオーバーヘッドを取り除きます)
  3. VMプロシージャのすべてのコードを1つの場所にコピーして、各命令の後にインタプリタに戻るのではなく、順番に実行できるようにします。

最終的には、JITコンパイル、オンラインプロファイリング、再最適化、およびその他のあらゆる種類のすばらしい機能のポイントに到達することになります。

于 2011-01-16T21:50:31.907 に答える
2

あなたが調べたいと思うかもしれない多くの良いテクニックがあります。これが私が精通している2つです:

  1. インラインキャッシング-基本的に、呼び出され続けるものを見つけてから、vtableルックアップから、静的に既知の場所にディスパッチする一連のifステートメントを追加するだけに切り替えます。この手法は、Self言語で大きな効果を発揮するために使用され、JVMの主要な最適化の1つです。

  2. トレース-最終的に使用される可能性のあるタイプごとにポリモーフィックディスパッチの一部の1つのバージョンをコンパイルしますが、コードが十分に何度も実行されるまでコンパイルを延期します。 MozillaのTraceMonkeyJavaScriptインタープリターはこれを使用して、多くの場合、パフォーマンスを大幅に向上させます。

お役に立てれば!

于 2011-01-16T21:45:16.707 に答える