JRubyいろいろ - 起動時オプション(コマンドラインオプション)
インストール編(http://d.hatena.ne.jp/yokolet/20100529#1275156722)に書いたどれか(もしかするとさらに他のインストール方法もあるかも。。。NetBeansに付いてきたとか)で、JRubyをインストールできたら、次は当然、使っちゃうぞー!でしょう。では、さっそく。
その1 動く?
定番、Hello Worldの前にやっておくのは、ほんとーにJRubyが動いている?を確認すること、ですね。Hello Worldが動かなかったときに、なにがまずいかを特定するためにも必要。ので、最初はコレ。
jrubyコマンドへのパスは通してあるよね!、じゃ、
jruby -v jruby 1.5.0 (ruby 1.8.7 patchlevel 249) (2010-05-12 6769999) (Java HotSpot(TM) Client VM 1.5.0_24) [i386-java]
バージョン番号、でたかな?まれに、JDKのバージョンと相性が悪くて動かないことがあるみたいです。すでに一年前の話しなので、状況は変わっていると思いますが、
http://kenai.com/projects/jruby/pages/JRubyOnUbuntu
http://kenai.com/projects/jruby/pages/JRubyOnHPUX11_23
なんかがあるので、JRubyが動いているかどうかの確認をお忘れなく。
その2 定番、Hello Worldは?
定番、定番。もう、コレをやらなきゃプログラミングは始まらないよねー。JRubyの場合、基本的にRubyと同じなので、
jruby -e"puts 'Hello World'" Hello World
とか、
jruby -e"puts \"Hello World\"" Hello World
とかして、-eオプションをつければ"(double quote)で囲まれた中を評価してくれる、と。日本語だって、
jruby -e"puts 'JRubyいいよぉ。使おうよ!'" JRubyいいよぉ。使おうよ!
というように、ちゃんと表示してくれます。
もう一つ、Rubyならではのirbを使ってHello Worldしてみるというのも、もちろんあります。JRubyにはirbの他にjirbという最初に"j"をつけたコマンドもあるのですが、一番よく使われているのは "jruby -S irb" ではないかと。なぜかというと、jrubyを使っているということがわかりやすいし、いろいろなオプションを指定したいときはコレが一番だからです。
jruby -S irb irb(main):001:0> puts 'JRubyいいよぉ。使おうよ!' JRubyいいよぉ。使おうよ! => nil irb(main):002:0>
その3 オプションいろいろ
と、ここまでで、すでに3つのコマンドラインオプション-v, -e -Sが出てきました。。。他には?、、、よりどりみどり揃えてございます。。。なのがJRuby。Rubyとはちょっと違うところですね。-hオプションを叩いてみると、、、
jruby -h Usage: jruby [switches] [--] [programfile] [arguments] -0[octal] specify record separator (\0, if no argument) -a autosplit mode with -n or -p (splits $_ into $F) -b benchmark mode, times the script execution -c check syntax only -Cdirectory cd to directory, before executing your script -d set debugging flags (set $DEBUG to true) -e 'command' one line of script. Several -e's allowed. Omit [programfile] -Fpattern split() pattern for autosplit (-a) -i[extension] edit ARGV files in place (make backup if extension supplied) -Idirectory specify $LOAD_PATH directory (may be used more than once) -J[java option] pass an option on to the JVM (e.g. -J-Xmx512m) use --properties to list JRuby properties run 'java -help' for a list of other Java options -Kkcode specifies code-set (e.g. -Ku for Unicode, -Ke for EUC and -Ks for SJIS) -l enable line ending processing -n assume 'while gets(); ... end' loop around your script -p assume loop like -n but print line also like sed -rlibrary require the library, before executing your script -s enable some switch parsing for switches after script name -S look for the script in bin or using PATH environment variable -T[level] turn on tainting checks -v print version number, then turn on verbose mode -w turn warnings on for your script -W[level] set warning level; 0=silence, 1=medium, 2=verbose (default) -x[directory] strip off text before #!ruby line and perhaps cd to directory -X[option] enable extended option (omit option to list) -y enable parsing debug output --copyright print the copyright --debug sets the execution mode most suitable for debugger functionality --jdb runs JRuby process under JDB --properties List all configuration Java properties (pass -J-Dproperty=value) --sample run with profiling using the JVM's sampling profiler --client use the non-optimizing "client" JVM (improves startup; default) --server use the optimizing "server" JVM (improves perf) --manage enable remote JMX management and monitoring of the VM and JRuby --headless do not launch a GUI window, no matter what --1.8 specify Ruby 1.8.x compatibility (default) --1.9 specify Ruby 1.9.x compatibility --bytecode show the JVM bytecode produced by compiling specified code --version print the version
いやぁ、けっこうあるね。Rubyな人にはお馴染みのオプションが半分くらいあるけれど、見たことがないオプションも結構あるかも。ところが、実はこれだけじゃあない。もっとあるんです。もうひとつのヘルプオプション --propertiesを付けてJRubyを起動してみると、、
jruby --properties These properties can be used to alter runtime behavior for perf or compatibility. Specify them by passing -J-D= COMPILER SETTINGS: jruby.compile.mode=JIT|FORCE|OFF Set compilation mode. JIT is default; FORCE compiles all, OFF disables jruby.compile.fastest=true|false (EXPERIMENTAL) Turn on all experimental compiler optimizations jruby.compile.frameless=true|false (EXPERIMENTAL) Turn on frameless compilation where possible jruby.compile.positionless=true|false (EXPERIMENTAL) Turn on compilation that avoids updating Ruby position info. Default is false jruby.compile.threadless=true|false (EXPERIMENTAL) Turn on compilation without polling for "unsafe" thread events. Default is false jruby.compile.fastops=true|false (EXPERIMENTAL) Turn on fast operators for Fixnum. Default is false jruby.compile.fastcase=true|false (EXPERIMENTAL) Turn on fast case/when for all-Fixnum whens. Default is false jruby.compile.chainsize= Set the number of lines at which compiled bodies are "chained". Default is 500 jruby.compile.lazyHandles=true|false Generate method bindings (handles) for compiled methods lazily. Default is false. jruby.compile.peephole=true|false Enable or disable peephole optimizations. Default is true (on). JIT SETTINGS: jruby.jit.threshold= Set the JIT threshold to the specified method invocation count. Default is 50. jruby.jit.max= Set the max count of active methods eligible for JIT-compilation. Default is 4096 per runtime. A value of 0 disables JIT, -1 disables max. jruby.jit.maxsize= Set the maximum full-class byte size allowed for jitted methods. Default is 10000. jruby.jit.logging=true|false Enable JIT logging (reports successful compilation). Default is false jruby.jit.logging.verbose=true|false Enable verbose JIT logging (reports failed compilation). Default is false jruby.jit.logEvery= Log a message every n methods JIT compiled. Default is 0 (off). jruby.jit.exclude= Exclude methods from JIT by class/module short name, c/m::method_name, or -::method_name for anon/singleton classes/modules. Comma-delimited. jruby.jit.cache=true|false Cache jitted method in-memory bodies across runtimes and loads. Default is true. jruby.jit.codeCache= Save jitted methods to as they're compiled, for future runs. NATIVE SUPPORT: jruby.native.enabled=true|false Enable/disable native extensions (like JNA for non-Java APIs; Default is true (This affects all JRuby instances in a given JVM) jruby.native.verbose=true|false Enable verbose logging of native extension loading. Default is false. jruby.fork.enabled=true|false (EXPERIMENTAL, maybe dangerous) Enable fork(2) on platforms that support it. THREAD POOLING: jruby.thread.pool.enabled=true|false Enable reuse of native backing threads via a thread pool. Default is false. jruby.thread.pool.min= The minimum number of threads to keep alive in the pool. Default is 0. jruby.thread.pool.max= The maximum number of threads to allow in the pool. Default is unlimited. jruby.thread.pool.ttl=
これらのオプションは
http://kenai.com/projects/jruby/pages/JRubyOptions
に一覧を作っておいてあるので、ざざっと眺めてくださいませ。この一覧はRedBridge(JRuby Embed)にコンフィグ用のメソッドをいろいろ追加するときに、ソースコードを眺めつつまとめたものです。とにかくやたらたくさんあって、なにがどうだったか忘れてしまうので。ただ、すべてのオプションがまともに動くワケではなくて、かなーりexperimentalなオプションも混じっているらしいので、中には"効かん!!"というのもあるかも。
オプションを改めて眺めるとよーくわかるのが、JRubyはやっぱりJavaのアプリケーションなんだということ。Javaのシステムプロパティやコマンドラインオプションを使ってJVMのコンフィグをする、というJavaな人には当たり前すぎる方法、でもRubyな人には未知の世界(?)な方法がいくつもあります。これらJavaなオプション使いこなしはJRuby使いこなし、スピードアップのためには必須なので、マスターすべし。だって、思ったでしょ。Hello Worldやirb起動して、"JRuby遅ぇ"って、MRIに比べたら。:)
その4 JRubyスピードアップのオプション
JRubyの名誉のため、念のため、言っておこうと思いますが、JRubyはそれなりのアプリケーションを動かす上では実行速度という点でMRIに決して引けはとりません(きっぱり)。起動は確かにMRIに比べて遅いけれど、一度立ち上がってしまえば早いんです。このあたりはHello Worldじゃわかりませんから。
それでもやっぱり実行速度は速いにこしたことはないし、"もっと速く!"という願いは不変なので、チューンアップ方法をいくつか。
Javaな人にはお馴染み、JVMにはclientモードとserverモードがありますよね。ぜひ、clientモードでお試しを。これは私自身も経験したのですが、、、、なんだかJDK 6だとミョウに遅い。JDK 5ならもっと速いのに、、、何だこの違いは?!と思ったら、JDK 5はclientがデフォルトでJDK 6はserverがデフォルトになっているのでした。その後、client/serverでのパフォーマンスの違いはIRCでも話題になっていて、"やっぱりね"と思った。この話しはCharles Nutter氏のブログ
Headius: JRuby Startup Time Tips
にも登場。ちなみに私のOS Xで試したら、
time jruby -J-server -ve "require 'rubygems'; require 'columnize'" jruby 1.5.0 (ruby 1.8.7 patchlevel 249) (2010-05-12 6769999) (Java HotSpot(TM) Server VM 1.5.0_24) [i386-java] real 0m1.741s user 0m2.214s sys 0m0.208s time jruby -J-client -ve "require 'rubygems'; require 'columnize'" jruby 1.5.0 (ruby 1.8.7 patchlevel 249) (2010-05-12 6769999) (Java HotSpot(TM) Client VM 1.5.0_24) [i386-java] real 0m1.315s user 0m1.090s sys 0m0.149s
な感じで、やっぱりclientを選ぶと速い。ところで、OS XのJDK 6だと -clientを指定しても常にserver JVMでしか起動しないのはバグなのかしら?UbuntuのOpenJDK 6はちゃんと切り替わったけれど。。。
- JITはOFFの方がいいときがある
Nutter氏のブログにもあるチューンナップから、もう一つ。JRubyのJIT compilerはOFFにした方が速い場合がある。なぜかというと、compileのプロセスが遅いから。JITが効きそうなプログラムの実行ならJITをONにしておいた方がみたいだけれど、そうじゃないときはOFFのほうがいいかも。-X-CでOFFにできます。ただ、"require 'rubygems'; require 'columnize'"の程度だと違いはびみょー。
- ObjectSpaceをOFFにすると速くなるかも
次はこちらにあるチューンアップから。
http://kenai.com/projects/jruby/pages/PerformanceTuning
ObjectSpaceというもの、私はあまり使ったことがないのですが、Rubyな人はよく使うのかな?「Ruby逆引きレシピ」だと、レシピ198の”オブジェクトが存在しているかを調べたい”で使ってますね。ま、必要無い場合、JRubyは-X-Oで無効にできます。さっきのJIT OFFと一緒に指定すると、、、
time jruby -J-client -X-C -X-O -ve "require 'rubygems'; require 'columnize'" jruby 1.5.0 (ruby 1.8.7 patchlevel 249) (2010-05-12 6769999) (Java HotSpot(TM) Client VM 1.5.0_24) [i386-java] real 0m1.217s user 0m1.041s sys 0m0.141s
気持ち、速くなっているかも。ちなみに、Performance TuningのドキュメントにあるThread Poolingの機能はアプリケーションによりけり、concurrentでびしばしさばいていかないといけないアプリじゃないと。この辺はJavaのマルチスレッドのノウハウを調べてから使った方がいいかも。--fastオプションも場合によりけり。遅くなることもあって、ビミョーなオプション。
- とりあえず -Xmx, -Xms。効くかも。
Java使いにとってはいにしえからのお友達です。heapサイズの最大、最小値を設定するJVMオプションですね。特に-Xms、最小値の方はstartup timeに効くはずなので、立ち上がりが速くなるはず。。。32MBを指定して試してみると、、、
time jruby -J-client -J-Xms32m -X-C -X-O -ve "require 'rubygems'; require 'columnize'" jruby 1.5.0 (ruby 1.8.7 patchlevel 249) (2010-05-12 6769999) (Java HotSpot(TM) Client VM 1.5.0_24) [i386-java] real 0m1.167s user 0m0.978s sys 0m0.138s
まったくオプション無し(-J-clientはディフォルトだから付けていない)の
time jruby -ve "require 'rubygems'; require 'columnize'" jruby 1.5.0 (ruby 1.8.7 patchlevel 249) (2010-05-12 6769999) (Java HotSpot(TM) Client VM 1.5.0_24) [i386-java] real 0m1.320s user 0m1.090s sys 0m0.148s
と比べると、速くなっているよね。たったこれだけのプログラムだから、違いはわずかだけれど。
JVMのオプションは
http://performance.netbeans.org/howto/jvmswitches/index.html
http://java.sun.com/javase/technologies/hotspot/vmoptions.jsp
なんていうのがあるし、Nutter氏は
Headius: My Favorite Hotspot JVM Flags
なんていうオタクなブログも書いているし、まだいろいろチューニングできそう。試してください、いろいろ。
ここでとりあげた以外にも、Nailgunを使う方法とか、Rubyのクラスをコンパイルしてしまう(http://kenai.com/projects/jruby/pages/JRubyCompiler)とか、JRubyには実行速度カイゼン方法がまだまだあります。よりどりみどり。いずれ、そのあたりも書きたいなぁ、と思う。
ところで、Nutter氏の"Startup Time Tips"、「近いうちに日本語訳します」って@hiro_asariが3月はじめにtweatしていたんだけれど、どこかで公開されているのかしら?”訳しました”とか”公開しました”とかいうのは見かけていないような‥
[追記]
日本語訳がようやく出たようです。