5

ruby 1.9.2p290(2011-07-09リビジョン32553)を使用[x86_64-linux]

私は多くのプロファイリングを行ってきましたが、rubyFixnumの乗算が非常に遅いことに気づきました。

いくつかのプロファイリングを通じて、Fixnum#*へのすべての呼び出しにはKernel#kind_ofへの6回の呼び出しが含まれるため、これは(部分的に)であることがわかりました。

C拡張機能を記述できることは知っていますが、これらの乗算はコード全体に広がっています。それで、Ruby内でこのオーバーヘッドを回避する方法はありますか?

ありがとう

4

2 に答える 2

5

いくつかの理由から、これらの測定値が正確であることを真剣に疑っています。

  1. 使用している Ruby の実装は明記されていませんruby-profが、Ruby プロファイラーです。Ruby コードをプロファイリングします。私が知っている Ruby 実装はありませんFixnum#*。Ruby コードがどこにあるかを知っています。MRI、YARV、MRuby、tinyrb では C コード、Rubinius では C++ コード、MacRuby では Objective-C コード、JRuby と XRuby では Java コード、RubyGoLightly では Go コード、IronRuby と Ruby では Go コードです。 NET では C# コード、MagLev と SmallRuby では Smalltalk コード、Cardinal では PASM コードです。ruby-profRuby コードのプロファイリングはできますが、C、C++、Objective-C、Java、C#、Go、Smalltalk、PASM のプロファイリングはできません。ルビーのみ。したがって、単純にプロファイルできませんFixnum#*

  2. Fixnum#*クラスを何度もチェックする必要はありません。それが であることを知っていselfますFixnum。そうでなければ、呼び出しはそもそもFixnum#*メソッドにディスパッチされないため、引数をチェックするだけで済みます。また、結果が a に収まるかどうかをチェックする必要がありますがFixnum、これは への呼び出しによってではなく、内部的に行われますkind_of?(実際、それは意味がありません: でメソッドを呼び出すことができるようにするためです)。乗算の結果を得るには、最初に結果オブジェクトを構築する必要があり、結果オブジェクトを構築するには、それが a に適合するかどうかを既に認識しているFixnum必要があります)。

  3. kind_of?Ruby のメソッド ルックアップとメソッド ディスパッチ機構全体を呼び出して調べて、そのクラス チェックを行うことはありません。これは Ruby 実装の内部関数であり、すべてのプライベートな内部実装の詳細にアクセスできます。Ruby メソッドではなく、クラスを直接チェックするか、内部インタープリター関数を呼び出すだけです。kind_of?

  4. Fixnum#*さまざまな一般的な Ruby 実装での実装を確認しましたが、への呼び出しは見つかりませkind_of?んでした。残念ながら、どの Ruby 実装を使用しているかは明らかにされていません。

于 2012-08-23T00:55:25.467 に答える
2

まあ、私はそれを理解したと思います。私は GSL ライブラリを使用していますが、ここで確認できるコードで Fixnum#* にパッチを適用しているようです: https://github.com/romanbsd/rb-gsl/blob/master/lib/gsl/oper.rb# L15

このコードには次のものが含まれています... 待ってください... Kernel#kind_of? への 6 回の呼び出し 大昔の「または」ステートメントで。

それがどのように機能するのか、なぜそれが起こるのかを完全に理解しているふりをするつもりはありませんが、コード パスはプロファイラーの出力と完全に一致します。

于 2012-08-23T15:45:29.647 に答える