BT

最新技術を追い求めるデベロッパのための情報コミュニティ

寄稿

Topics

地域を選ぶ

InfoQ ホームページ ニュース Rubyパフォーマンス総まとめ:Heap Stackによる1.8.xのスレッドの高速化、MacRuby AOT、ZenProfileとEventHook

Rubyパフォーマンス総まとめ:Heap Stackによる1.8.xのスレッドの高速化、MacRuby AOT、ZenProfileとEventHook

原文(投稿日:2009/5/23)へのリンク

Ruby 1.9はRubyの世界を1.8.xのユーザ空間スレッドシステムからネイティブスレッドのシステムに変えた。1.9のネイティブスレッドはGVL (Global VM Lock:大域的な仮想マシンのロック)に苦しんでいて、それによって一度にたった1つのRubyスレッドしか実行することができないが、ネイティブスレッドへの移行は別の恩恵をもたらした。

Joe Damato氏はRuby 1.8.xのスレッド実装の問題があり、その問題が1.9のネイティブスレッドではなくなっていることを明らかにした。手短に言うと: 1.8.xではコンテキストスイッチの効率がかなり悪いのだ。それはスレッドの完全なスタックの中身を(中断するスレッドに対しては)スタックからヒープへ、スケジュールされたスレッドに対してはその反対方向にコピーすることに原因がある。大きなスタックを持っていたり、大きなスタックフレームを持っているアプリケーションはこの実装の詳細に苦しめられているのだ。

ネイティブスレッド実装は複数のスタックを管理してそれらを取り替えることでこの非効率なことが起こらないようにしている。Joe氏の投稿はこのアプローチをRuby 1.8.xにもたらす彼の"heap stacks"についての非常に詳細な説明になっている。
パフォーマンスの改善は著しく、2倍から10倍も増加しており、そのベンチマーク結果は1.9.1のベンチマーク結果に近いところまできている。
コードのパッチがあたったバージョンはGitHubで利用可能である: 1.8.6向け1.8.7向け

Heap Stackソリューションは継続とGCのいくつかの長く存在していた問題を修正するMBARIパッチと並んで、Ruby1.8.xの最大の非効率性を根絶するもう一つの試みである。

Rubyのパフォーマンスをよりよくする別の道がMacRubyプロジェクトから始まっていて、そこでは最近LLVMをベースとしたVMに関する作業が始まっている。その作業のいくつかはすでにRubyの事前 (Ahead Of Time, AOT) コンパイラをつくるのに使われている。 ここで、AOTとはジャストインタイム (Just In Time)コンパイラと対比的なもの、すなわち、実行時にコンパイルする代わりに、AOTコンパイラを実行するとソースコードから実行形式を生成する:

表現(ソースコード)はまずLLVM中間表現に、そのあとでビットコードに、さらにアセンブリに、そして機械語にコンパイルされるんだ。本当のコンパイルだよ:-)

このことが有用なシナリオがたくさんある:

1) コードの難読化、2) 動的コード生成が許されない環境においてRubyを利用する、などにとって有用となるだろうね:)


最後に、プロファイラはアプリケーションのボトルネックを明らかにする1つの方法である。Ryan Davis氏は彼のZenprofileプロファイラを更新し、メソッド呼び出しを追跡する効率的な方法としてRubyランタイムにおけるイベントフックを利用するようにした。Zenprofileはここしばらく使われているが、更新されたバージョンでは、フックを設定するためのネイティブコードの必要性を取り除いたevent_hook gem に依存するようになっている。event_hookを使うことで、今やRubyインタープリタにフックをかけるためにネイティブコードを書く必要はなく、純粋なRubyのイベントフックを書くだけでよい。Zenprofileはそれを利用して、そのプロファイリングロジックの純粋なRubyバージョンと、ネイティブコードに対してRubyInlineとCを利用したより高速なバージョンを提供している。

Zenprofileのコードをざっと見たところ、event_hookを利用するにはEventHookクラスを拡張して、イベントを捕獲するためにdef self.process event, obj, method, klass のようなわずかなメソッドをオーバーライドするくらいという簡単さのようだ。

Zenprofileはまたspy_on機能を提供していて、それによって個々のメソッドのパフォーマンスに焦点を当てることが可能である。この機能はRubyのコードで設定が可能である。たとえば、Integer#downtoに焦点を当てたい場合、次のmisc/factorial.rbに記述されている例のように書けばよい:

require 'spy_on'
Integer.spy_on :downto  

この記事に星をつける

おすすめ度
スタイル

BT