Wednesday, May 13, 2009

JRuby Nailgun Support in 1.3.0

I've merged changes into master (to be 1.3 soon) that should make Nailgun easier to use. And 1.3 will be the first release to include all NG stuff in the binary dist.

  • jruby --ng-server starts up a server. You can manage it however you like
  • jruby --ng uses the Nailgun client instead of launching a new JVM for the command you run. You'll just need to run make in tool/nailgun to build the ng executable (already built for you on Windows).
Future improvements will include having --ng start up the server for you if you haven't started it, passing signals through (don't expect signals to work at all right now), better management of threads and commands, and so on. But it's a good start, and people can try to play with it and report issues more easily now.

Heres a sample session:
~/projects/jruby ➔ cd tool/nailgun/ ; make ; cd -
Building ng client. To build a Windows binary, type 'make ng.exe'
gcc -Wall -pedantic -s -O3 -o ng src/c/ng.c
ld warning: option -s is obsolete and being ignored
/Users/headius/projects/jruby

~/projects/jruby ➔ jruby --ng-server
NGServer started on all interfaces, port 2113.
^Z
[1]+ Stopped jruby --ng-server

~/projects/jruby ➔ bg
[1]+ jruby --ng-server &

~/projects/jruby ➔ jruby --ng -e "puts 1"
1

~/projects/jruby ➔ time jruby -e "puts 1"
1

real 0m0.609s
user 0m0.482s
sys 0m0.119s

~/projects/jruby ➔ time jruby --ng -e "puts 1"
1

real 0m0.073s
user 0m0.010s
sys 0m0.018s

Update: For those not familiar, "NailGun is a client, protocol, and server for running Java programs from the command line without incurring the JVM startup overhead. Programs run in the server (implemented in java), triggered by the client (written in C), which handles all I/O."

Update 2: It's been brought to my attention that we no longer ship a pre-configured Makefile for the ng client, so your build command line should actually look like:
~/projects/jruby ➔ cd tool/nailgun/ ; ./configure ; make ; cd -
Alternatively, you can run "ant build-ng" in the JRuby root, which will do largely the same thing for you using Ant.

15 comments:

Matt Aimonetti said...

For comparison when not using NG:
$ time jruby -e "puts 1"
1

real 0m5.357s
user 0m0.504s
sys 0m0.191s
That's a huge difference, and it should make JRuby web app deployments much better.

Thanks guys!

- Matt

Martin Probst said...

I'm still dreaming of someone to build a comprehensive Java command line toolkit.

Nailgun, a fixed version of JLine, a reasonable command line options parser (all the ones out there are unmaintained and/or crap...).

Charles Oliver Nutter said...

Martin: I'm an admin on Jline now, so if there's fixes you think need to get in jump on the ML and say so. We can put out a release.

Ben Atkin said...

This will make running JRuby from non-Java-based editors much easier, since the plugin writers won't have to manually wire up Nailgun. Thanks!

mernen said...

Are there any known input/stdin problems? I can't get irb to run appropriately.

Charles Oliver Nutter said...

Mernen: Yes, it appears that jirb does not work at the moment. We'll have to track down exactly what's wrong with it. When I try it, I see it launching stty (part of JRuby startup I think) and never getting any further...

Can you file a bug for it please?

Martin Probst said...

Charles: that is very good news that JLine is maintained again. I'll file some bugs with SourceForge if you don't mind.

Charles/Mernen:
About the blocking stty call: I guess I ran into that bug here, too. The issue (at least the one I had) is that JLine is calling stty when initializing a terminal.

Now the issue is that in your nailgun setup, or in the case where you pipe input to a command ("cat foo | jruby --ng"), the input stream is not really terminal, and stty thus blocks. I can't quite find the correct man pages etc now, but I think that was the issue. On some UNICes (Linux in particular if I remember correctly), it is possible to give stty a parameter telling it not to block, but I can't quite find the reference.

Joakim said...

Tried this with loading a rails environment.

With NG:
time jruby --ng -e 'require "config/environment"'
real 0m26.159s
user 0m0.011s
sys 0m0.021s

Without NG:
time jruby -e 'require "config/environment"'

real 0m16.967s
user 0m14.659s
sys 0m1.176s

(the simple puts example worked as shown in the blog post)

Rob said...

On sourceforge? Really?

Anonymous said...

See http://jira.codehaus.org/browse/JRUBY-3867 for a required patch of the windows batch files (patch included JRuby 1.4).

sumuhan said...

Hi,
I tried this on windows but using the nail gun option actually seems to slow things down!
Here is what i did

1)opened a command line and started ng server


H:\>jruby --ng-server
NGServer started on all interfaces, port 2113.


2) opened two other command lines and tried starting the rail environment with and without ng

here are the results

with --ng

D:\rubylearn\RailsApplication1>jruby --ng -e 'require "config/environment"'
initializer about to startFri Jul 02 09:24:04 +0100 2010
initializer finishedFri Jul 02 09:24:40 +0100 2010

D:\rubylearn\RailsApplication1>jruby --ng -e 'require "config/environment"'
initializer about to startFri Jul 02 09:26:54 +0100 2010
initializer finishedFri Jul 02 09:27:19 +0100 2010

D:\rubylearn\RailsApplication1>jruby --ng -e 'require "config/environment"'
initializer about to startFri Jul 02 09:28:00 +0100 2010
initializer finishedFri Jul 02 09:28:21 +0100 2010


without --ng

D:\rubylearn\RailsApplication1>jruby -e 'require "config/environment"'
initializer about to startFri Jul 02 09:24:50 +0100 2010
initializer finishedFri Jul 02 09:25:02 +0100 2010

D:\rubylearn\RailsApplication1>jruby -e 'require "config/environment"'
initializer about to startFri Jul 02 09:27:43 +0100 2010
initializer finishedFri Jul 02 09:27:55 +0100 2010

D:\rubylearn\RailsApplication1>jruby -e 'require "config/environment"'
initializer about to startFri Jul 02 09:29:01 +0100 2010
initializer finishedFri Jul 02 09:29:13 +0100 2010

Am I doing something wrong?

I didn't do anything special to setup nail gun. It seems to be already there with jruby I guess.

My jruby version is

H:\>jruby -v
jruby 1.5.0 (ruby 1.8.7 patchlevel 249) (2010-06-10 6586) (Java HotSpot(TM) Client VM 1.6.0_14) [x86-java]

Charles Oliver Nutter said...

sumuhan: Notice that your times were still getting shorter after a few launches using --ng. Try a few more times and if it doesn't at least match the non --ng way, file a bug.

Also, --ng largely helps improve the startup time before your initializer would even run; if you benchmarked wall clock time for that portion, it should almost certainly be faster.

sumuhan said...

Hi Charles,
I tried your suggestion. This time it is a different PC (Earlier I tried work PC, this time it is my dell laptop at home) I created a blank rails app through netbeans. Then got back to command line and repeated the experiment but this time I timed the complete wall time as you have suggested

But in the end there is still a huge difference in performance. Plain jruby seem to run circles around nailgun.

Jruby starts it in 10 seconds. And nailgun takes about a minute. After running ng ten times ng there is no big difference in the time taken.

with ng after about 10 runs....

C:\ngtest\RailsApplication1>jruby --ng -e 'puts Time.now; require "config/environment";puts Time.now'
Sat Jul 03 00:07:40 +0100 2010
Sat Jul 03 00:08:33 +0100 2010

Now without ng we get..

C:\ngtest\RailsApplication1>jruby -e 'puts Time.now; require "config/environment";puts Time.now'
Sat Jul 03 00:09:29 +0100 2010
Sat Jul 03 00:09:38 +0100 2010

So looks like I have hit a bug. Can you post the url for filing bugs please?

Charles Oliver Nutter said...

sumuhan: Thanks for helping track this down! You can simply go to http://bugs.jruby.org and be redirected to our JIRA instance.

sumuhan said...

Thanks for your help Charles. Just filed a bug!