22

私は Ruby のパフォーマンスについて読み込もうとしていて、この SO スレッドに出くわしました。回答の 1 つで、「Ruby で最も一般的な操作の 1 つであるメソッド呼び出しが特に遅い」と述べられています。

別のスレッドは、「柔軟性を確保するために、メソッドの「レイトルックアップ」を行います。これにより、かなり遅くなります。また、評価を可能にするためにコンテキストごとに名前を覚えておく必要があるため、フレームとメソッドの呼び出しが遅くなります。」

Ruby のメソッド呼び出しが特に遅い理由を詳しく説明し、2 番目のスレッドについて詳しく説明してもらえますか? レイト ルックアップとは何か、なぜ遅いのか、完全にはわかりません。また、コンテキストごとの名前が何を意味するのか、それがフレームやメソッド呼び出しとどのように関係しているのかもわかりません。

私の (おそらく間違った) 理解では、メソッドは実行時に追加または変更できるため、Ruby インタープリターは特定のメソッドの実行方法を「記憶」することはできないため、プログラムの実行中に毎回メソッドを検索する必要があります。メソッド呼び出しが遅いという意味です。しかし、修正とより技術的な説明は素晴らしいでしょう.

4

1 に答える 1

20

コンパイルされた言語では、メソッド ポインターの配列であるクラスの vtable へのインデックスを呼び出し元のコードが認識しているため、多くの場合、高速なメソッド ディスパッチが行われます。わずか数回のポインター逆参照の後、呼び出し元のコードはメソッドに直接ジャンプできます。コンパイラは vtable を作成し、ソース コード内のすべてのメソッド名を vtable 内のメソッドの数値インデックスに置き換えます。

Ruby などの動的言語は、呼び出し元のコードに名前があるため、メソッドのディスパッチが遅いことがよくあります。メソッドの場合、ポインターではありません (ポインターを含む配列へのインデックスでもありません)。呼び出し元のコードは、オブジェクトにそのクラスを問い合わせる必要があり、次に、その名前のメソッドがあるかどうかをクラスに問い合わせる必要があります。ない場合は、祖先のチェーンをたどって、各祖先にその名前のメソッドがあるかどうかを問い合わせます (これは、コンパイラがコンパイル済み言語で行うことです。これが、コンパイルが遅く、メソッドのディスパッチが速い理由です)。動的言語は、メソッドを呼び出すためにわずか数個の機械語命令を必要とする少数のポインター逆参照ではなく、数十から数百の機械語命令を実行して、オブジェクトのクラスとすべてのオブジェクトの祖先クラスでメソッドを検索する必要があります。各クラスには、名前 -> メソッドの HashTable がありますが、文字列キーを持つ HashTable は、整数インデックスを持つ配列よりも桁違いに遅くなります。

もちろん、動的言語でメソッドのディスパッチを最適化する方法はあります。Ruby では、JRuby、Rubinius、IronRuby が取り組んでいるものです。しかし、それは別の質問の主題です。

于 2011-06-20T02:37:27.917 に答える