読者です 読者をやめる 読者になる 読者になる

”+”の評価ですらコンパイル時ではなく実行時にしなくちゃいけなくてひょえ〜〜。

Hiro Yoshioka on Twitter: "@_tad_ ”+”の評価ですらコンパイル時ではなく実行時にしなくちゃいけなくてひょえ〜〜。"

言語仕様として重い仕様があって、それをやめちゃおうというRISC思想です。

Hiro Yoshioka on Twitter: "@NeoCat 言語仕様として重い仕様があって、それをやめちゃおうというRISC思想です。"

この辺。

Number#+とかの頻出するメソッド呼出しに対して特価命令*1を定義しておいて、それを使う、というのは、現在のRubyの仕様でもできると思う。なので、言語仕様で常に+の本体を静的に解決できるようにしても、高速化できるかというと、微妙なような気がする。

感覚だけで言ってるので、全然外してるかもしれませんけど。


実際の実装(YARV)でも、+が再定義されていない場合に限って、特価命令を使う、みたいな手法が取り入れられてたと思う。さらにJITなりフロー解析なりすれば、この辺をもっとかしこくすることは可能なはず。

で、こういう最適化ができたとすると、

[1, "a", 1.0, 100000000000000000000000000000000000].each {|a|
  a + 3
}

みたいなコードがあった場合に、

[1, "a", 1.0, 100000000000000000000000000000000000].each {|a|
  case a
  when Fixnumだったら: Fixnum用のa+3
  when Stringだったら: String用のa+3
  when Floatだったら: Float用のa+3
  when Bignumだったら: Bignum用のa+3
  else
    a + 3
  end
}

とかなるんじゃないかと思う(これが違ってたら話にならない)。

で、これって、+の定義が静的に解決できる場合と同じコードになるんじゃないか。


という直感で「高速化できないんじゃないかなー」と思ってる。


こういう最適化ができない場合はあるか?

まず、caseの候補が多過ぎる場合は、無理だろう。あんまりばかでかいコードに展開されるのは、いろいろと苦しいんじゃないかと思う。この辺はよくわからない。実際のアプリケーションでどうなるのか、調べてみる方が良いと思う。ただし、僕の(ほんの少しの)経験から言えば、ループの内側とかで候補がすごく多くなるケースは少ないような気がする。

次に、〜〜だったらの条件分岐が遅い場合も効果は無いだろう。まあ、これだって、候補が少なければ高速に実行されるように最適化することはできるような。

あとは、〜〜だったら、の候補の出現頻度にものすごく偏りがある場合とかも上手く効かないかもしれないけど、それこそJITで解決できる問題のはずだし。

*1:実行時間40%OFF!!