« カーネル | トップページ | Hacking Ruby by Fridge / 2 »

Hacking Ruby by Fridge

夜中に目がさえてしまったのでfridgeを使ってrubyをハッキングする. まぁあんまfridge関係ないけど.
下準備としてrubyをデバッグモード(最適化オプションを外して)コンパイルしておく.
以下がハッキング用fridgeソース

      1 #!/usr/bin/fridge
      2
      3 # ruby src -------------------------------
      4 rSrc="""
      5
      6 i=0
      7 while i<10000000
      8     i+=1
      9 end
     10 p i
     11
     12 """
     13 # getting profile -------------------------
     14 opcontrol, --reset
     15 opcontrol, --start
     16 pwrite "time ./ruby" rSrc
     17 opcontrol, --shutdown
     18 opreport ,-l | head

これぞfridgeによるインラインruby.
fridgeではどんなスクリプト言語でもインライン展開することができる(なんの役に立つかはわからないけど).
中身は簡単.oprofileを起動してrubyスクリプトの部分のプロファイルを取るだけ.
結果は以下の通り.

samples  %        image name  app name  symbol name
2708     49.1738  ruby        ruby      rb_eval
1203     21.8449  ruby        ruby      rb_call0
751      13.6372  ruby        ruby      rb_call
238       4.3218  ruby        ruby      call_cfunc
230       4.1765  ruby        ruby      fix_plus
148       2.6875  ruby        ruby      fix_lt
101       1.8340  ruby        ruby      rb_class_of

rb_eval(eval.c)という関数が重いんだけど,中身を見たら

   2908   again:
   2909     if (!node) RETURN(Qnil);
   2910
   2911     ruby_current_node = node;
   2912     switch (nd_type(node)) {
   2913       case NODE_BLOCK:
   2914         if (contnode) {
   2915             result = rb_eval(self, node);
   2916             break;
   2917         }
   ...         

という長いcase文になっていて,たぶんここの部分を関数ポインタのリストとかにすれば だいぶ速くなるんじゃないかと思った.
パッチつくろうかと思ったけどけっこう量がありそうだし, 明日は彼女とディズニーランドに遊びに行くので今日は寝る.
誰か興味があったらやってみてくれるとうれしい.

そのうちfirefoxのハックとかもやってみようかと思ってる.

関連
ruby本家:ruby公式サイトです.
Matzにっき:作者のMatzさんのにっき
ユメのチカラ:oprofileによるrubyのハックやってます.色々教えてもらいました(すごく助かってます).
fridge home page:宣伝

« カーネル | トップページ | Hacking Ruby by Fridge / 2 »

コメント

十年位前に関数ポインタを埋め込むというハックはやったことがありました。1週間近くかかったのにほとんど変わらずショックを受けました。

なぜほとんど変わらなかったのか詳細を検討する前にディスククラッシュでソースを失ったのがもっとショックでした。それ以来、試していません。

それはドラマティックなほど悲惨でしたね...十年前というと僕はちょうど中学に入ったばかりで,毎日学校帰りの駄菓子屋でのり巻きせんべえばかり食べていた記憶があります.
関数ポインタで速度が変わらないとは,gotoによるくり返しが速いのか,ボトルネックが条件分岐の演算じゃないのか...
おもしろそうなので時間を見つけてまたちょっと調査してみますね.

opreport -dg
は、どうなっているでしょうか?
どこがボトルネックになっているか精密に知ることが第一歩かと思います。

関数ポインタはキャッシュミスをするので遅くなりそうな予感はしますね。

詳細はこんな感じです.

#opreport -dg

---------------------
4 vma samples % linenr info app name symbol name
5 0805698b 2497 47.6436 eval.c:2897 ruby rb_eval
6 0805698b 73 2.9235 eval.c:2897
7 0805698c 8 0.3204 eval.c:2897
8 0805698e 37 1.4818 eval.c:2897
9 0805698f 16 0.6408 eval.c:2897
10 08056991 41 1.6420 eval.c:2897
11 08056997 4 0.1602 eval.c:2898
12 0805699e 34 1.3616 eval.c:2899
13 080569a1 18 0.7209 eval.c:2899
14 080569a4 40 1.6019 eval.c:2901
15 080569ab 4 0.1602 eval.c:2909
16 080569ae 125 5.0060
...
23 080569d6 41 1.6420 eval.c:2913
24 080569dc 47 1.8823 eval.c:2913
25 080569e3 178 7.1286 eval.c:2913
26 080569e9 42 1.6820 eval.c:2913
27 080569ef 3 0.1201 eval.c:2913
28 080569f6 111 4.4453 eval.c:2913
29 080571f3 7 0.2803 eval.c:3098
30 080571fc 4 0.1602 eval.c:3098
...
115 0805a7a5 5 0.2002 eval.c:4103
116 0805a7b6 42 1.6820 eval.c:4109
117 0805a7bd 5 0.2002 eval.c:4109
118 0805a7bf 47 1.8823 eval.c:4109
119 0805a7c6 2 0.0801 eval.c:4109
120 0805a7c8 51 2.0425 eval.c:4109
121 0805a7cf 25 1.0012 eval.c:4109
122 0805a7d6 48 1.9223 eval.c:4109
123 0805a7dd 11 0.4405 eval.c:4109
124 0805a7e4 38 1.5218 eval.c:4110
125 0805a7fd 31 1.2415 eval.c:4115
126 0805a804 50 2.0024 eval.c:4116
--------------------

これを見ると関数の始まり,switch文のはじまり、おわり、関数の終わりが負荷が高いように見えるんですが,これはどのノードも共通の処理なので当然といえば当然ですね.
キャッシュミスが計測できないのが口惜しいです.

コメントを書く

コメントは記事投稿者が公開するまで表示されません。

(ウェブ上には掲載しません)

トラックバック

この記事のトラックバックURL:
http://app.f.cocolog-nifty.com/t/trackback/163977/3742213

この記事へのトラックバック一覧です: Hacking Ruby by Fridge:

« カーネル | トップページ | Hacking Ruby by Fridge / 2 »