JRuby

Javaコマンドラインからインタープリタ使えないのかなーと思って、google先生に'java インタープリタ irb'って聞いてみたら、JRubyなるものが出てきた。Javaで書いたRuby。ひょっとして使えるのでは? と思って早速試す。rubyコマンドの代わりにjrubyコマンドを使えば、ほぼそのままrubyとして使える。jirbもある。それだけでは何も嬉しくないわけで、売りは何かというと、Javaのオブジェクトへのアクセスである。例えばスクリプトからSwing::JFrame.newできたりするのだ。当初の目的は、java.lang.Stringにはsplitメソッドってあるのかなー、みたいなところにあるので、辛うじて達成できそうなのだが、ふつうにString.new()してしまうとJRubyのStringクラスになってしまうので、

irb(main):049:0> require 'java'
=> true
irb(main):050:0> String s = String.new('abcde')
=> "abcde"
irb(main):051:0> s
=> "abcde"

JavaのStringクラスを試すには、java.lang.String.new()しなければダメっぽい。

irb(main):052:0> String s = java.lang.String.new('abcde')
=> "abcde"
irb(main):053:0> s
=> #<#<Class:01x18e9640>:0x14b6e28 @java_object=abcde>
irb(main):054:0> s.toUpperCase
=> "ABCDE"

つまり、Rubyで同じ名前のオブジェクトが存在するものは、クラスライブラリのフルパスを知ってなければならないわけで、結局この用途での実用は厳しいか...

ひょっとして速いのかなーと思い、一応簡単に確認。
ふつーのRubyスクリプト

hao% cat test.rb
s = 'abcdefg12345abcdefg12345'
for i in 1..10000
s.match('^abcde')
s.match('^.*12345.*$')
s.match('^.*abcde.*$')
end
hao% time ruby test.rb
ruby test.rb  0.21s user 0.01s system 97% cpu 0.224 total

JRubyをふつーに使った場合(JRubyのStringオブジェクト)

hao% cat test2.jrb
s = 'abcdefg12345abcdefg12345'
for i in 1..10000
s.match('^abcde')
s.match('^.*12345.*$')
s.match('^.*abcde.*$')
end
hao% time jruby test2.rb
jruby test.rb  6.90s user 0.13s system 99% cpu 7.037 total

期待はしていなかったが、激しく遅い。
さらに、Javaオブジェクトを使うようにしたらもしかして、と淡い期待を抱いたのだが...
JRubyスクリプトJavaのStringを使った場合

hao% cat test.jrb
require 'java'

s = java.lang.String.new('abcdefg12345abcdefg12345')
for i in 1..10000
s.matches('^abcde')
s.matches('^.*12345.*$')
s.matches('^.*abcde.*$')
end
hao% time jruby test.jrb
jruby test.jrb  10.85s user 0.14s system 99% cpu 11.068 total

全然だめだ。もともとRubyのStringオブジェクトだって本体はネイティブコードになってるわけで、そこは決して速くはならない。その上、メッセージパッシングはめっちゃ重い、ってことなんだろう。考えてみれば当たり前だが。