# JRuby 1.3.0 will include Nailgun

**URL:** <https://www.ruby-forum.com/t/jruby-1-3-0-will-include-nailgun/167919>\
**Category:** Ruby\
**Created:** [May 13, 2009, 11:46pm UTC](https://www.ruby-forum.com/t/jruby-1-3-0-will-include-nailgun/167919 "2009-05-13T23:46:09Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![headius](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/7c8e57/32.png) [@headius](https://www.ruby-forum.com/u/headius)\
**Post date:** [May 13, 2009, 11:46pm UTC](https://www.ruby-forum.com/t/jruby-1-3-0-will-include-nailgun/167919/1 "2009-05-13T23:46:09Z")

</div>

Nailgun is a tool that speeds up Java command startup by punting  
commands to an always-running “server” JVM. The improvement for JRuby is  
substantial, with bare-bones startup times improving tenfold.

There’s work to be done, like to get signals to forward from the client  
to the server and to more easily manage server instances, but it’s a  
good start. We’re looking for people to try it out (to be released in  
RC2 soon) and give us feedback.

> **[JRuby Nailgun Support in 1.3.0](http://blog.headius.com/2009/05/jruby-nailgun-support-in-130.html)**
>
> 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 likejruby --ng...

Here’s a short sample session using JRuby with Nailgun:

~/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

- Charlie

---

<div class="post-metadata">

**Author:** ![headius](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/7c8e57/32.png) [@headius](https://www.ruby-forum.com/u/headius)\
**Post date:** [May 14, 2009, 11:25am UTC](https://www.ruby-forum.com/t/jruby-1-3-0-will-include-nailgun/167919/2 "2009-05-14T11:25:01Z")

</div>

On Thu, 14 May 2009 06:45:25 +0900, Charles Oliver N. wrote:

> Nailgun is a tool that speeds up Java command startup by punting  
> commands to an always-running “server” JVM. The improvement for JRuby  
> is substantial, with bare-bones startup times improving tenfold.

This is so cool. I’ve been wanting something like it forever.

Is the nailgun implementation similar in concept to perperl (or  
PersistentPerl, [PersistentPerl - Speed up perl scripts by running them persistently.](http://daemoninc.com/PersistentPerl/))? Is there anything  
like it for MRI as well? In your opinion, would it be feasible?

Kudos!

David

---

<div class="post-metadata">

**Author:** ![headius](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/7c8e57/32.png) [@headius](https://www.ruby-forum.com/u/headius)\
**Post date:** [May 14, 2009, 12:16pm UTC](https://www.ruby-forum.com/t/jruby-1-3-0-will-include-nailgun/167919/3 "2009-05-14T12:16:53Z")

</div>

David P. wrote:

> This is so cool. I’ve been wanting something like it forever.
> 
> Is the nailgun implementation similar in concept to perperl (or  
> PersistentPerl, [PersistentPerl - Speed up perl scripts by running them persistently.](http://daemoninc.com/PersistentPerl/))? Is there anything  
> like it for MRI as well? In your opinion, would it be feasible?

It would be wonderful if it could have all the Rails Active\* libraries  
preloaded; that would drastically shorten the startup time for unit  
tests etc.

I don’t see in principle why it couldn’t be done - I guess you just fork  
the process when a request comes in. The messy bit is passing the  
stdin/stdout/stderr file descriptors over a socket. And it could be  
called “railgun” 🙂

---

<div class="post-metadata">

**Author:** ![headius](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/7c8e57/32.png) [@headius](https://www.ruby-forum.com/u/headius)\
**Post date:** [May 14, 2009, 1:48pm UTC](https://www.ruby-forum.com/t/jruby-1-3-0-will-include-nailgun/167919/4 "2009-05-14T13:48:26Z")

</div>

Unfortunately, the name ‘railgun’ has been taken by a games library ☹

---

<div class="post-metadata">

**Author:** ![headius](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/7c8e57/32.png) [@headius](https://www.ruby-forum.com/u/headius)\
**Post date:** [May 14, 2009, 1:40pm UTC](https://www.ruby-forum.com/t/jruby-1-3-0-will-include-nailgun/167919/5 "2009-05-14T13:40:38Z")

</div>

Brian C. wrote:

> I don’t see in principle why it couldn’t be done - I guess you just fork  
> the process when a request comes in. The messy bit is passing the  
> stdin/stdout/stderr file descriptors over a socket. And it could be  
> called “railgun” 🙂

It turns out all the messy passing of IO objects is already included in  
the Ruby standard socket library, so without further ado, here’s a  
working proof-of-concept 🙂 Tested under ruby 1.8.6p111

$ cat hello.rb

# Silly program which requires active\_support to work

puts ‘’.blank?

$ time ruby -rubygems -e’require “active\_support”’ -e ‘load “hello.rb”’  
true

real 0m1.522s  
user 0m1.280s  
sys 0m0.216s

$ ruby -rubygems -railgun -e’require “active\_support”’  
Railgun PID 10272 started

[in another console]  
$ time ./rg 10272 hello.rb  
true

real 0m0.076s  
user 0m0.036s  
sys 0m0.012s

---- 8\< ---- ailgun.rb ----

# Sample usage:

# ruby -rubygems -railgun -e’require “active\_support”’

# Note that at least one ‘-e’ option is required, e.g. -e0

at\_exit do  
require ‘socket’  
sockname = “/tmp/railgun#{$$}”  
File.delete(sockname) rescue nil  
trap(‘INT’) { File.delete(sockname) rescue nil; exit! }  
server = UNIXServer.open(sockname)  
puts “Railgun PID #{$$} started”  
while client = server.accept  
fork do  
begin  
STDIN.reopen(client.recv\_io)  
STDOUT.reopen(client.recv\_io)  
STDERR.reopen(client.recv\_io)  
# [script, args] # TODO: interpret flags like -I and -r  
nbytes = client.read(4).unpack(“N”).first  
args = Marshal.load(client.read(nbytes))  
client.close  
cmd = args.shift  
ARGV.replace(args)  
load cmd  
rescue Exception =\> e  
STDERR.puts e  
client.close rescue nil  
end  
end  
client.close  
end  
end  
---- 8\< ----

---- 8\< ---- rg.rb ----  
#!/usr/bin/env ruby

# Usage: ruby rg.rb \<args…\>

require ‘socket’  
pid = ARGV.shift  
server = UNIXSocket.open("/tmp/railgun#{pid}")  
args = Marshal.dump(ARGV)  
server.send\_io(STDIN)  
server.send\_io(STDOUT)  
server.send\_io(STDERR)  
server.write [args.size].pack(“N”)  
server.write args  
---- 8\< ----

The awkward thing from a user point of view is that you have to remember  
the pid of where the railgun server is. You could use a fixed name, but  
that would only let you have a single railgun process preloaded with a  
single set of libraries.

Perhaps it would be better for the railgun server to drop you into a new  
shell which has something in the ENV with this information.

---

<div class="post-metadata">

**Author:** ![headius](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/7c8e57/32.png) [@headius](https://www.ruby-forum.com/u/headius)\
**Post date:** [May 14, 2009, 6:38pm UTC](https://www.ruby-forum.com/t/jruby-1-3-0-will-include-nailgun/167919/6 "2009-05-14T18:38:43Z")

</div>

> It turns out all the messy passing of IO objects is already included in  
> the Ruby standard socket library, so without further ado, here’s a  
> working proof-of-concept 🙂 Tested under ruby 1.8.6p111

Wow. You got me all excited now!

🙂

---

<div class="post-metadata">

**Author:** ![headius](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/7c8e57/32.png) [@headius](https://www.ruby-forum.com/u/headius)\
**Post date:** [May 14, 2009, 10:15pm UTC](https://www.ruby-forum.com/t/jruby-1-3-0-will-include-nailgun/167919/7 "2009-05-14T22:15:43Z")

</div>

David P. wrote:

> Wow. You got me all excited now!

I’ve tidied it up a little and pushed the code to

> **[GitHub - candlerb/snailgun: Preload and fork ruby interpreter for fast script...](https://github.com/candlerb/snailgun/tree/master)**
>
> master

However, don’t get too excited - it doesn’t play particularly well with  
Rails yet. In particular, “frake test:units” doesn’t run any tests. I’m  
afraid I don’t have time to investigate further.

Regards,

Brian.

---

<div class="post-metadata">

**Author:** ![headius](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/7c8e57/32.png) [@headius](https://www.ruby-forum.com/u/headius)\
**Post date:** [May 14, 2009, 5:09pm UTC](https://www.ruby-forum.com/t/jruby-1-3-0-will-include-nailgun/167919/8 "2009-05-14T17:09:29Z")

</div>

Brian C. wrote:

> Brian C. wrote:
> 
> > I don’t see in principle why it couldn’t be done - I guess you just fork  
> > the process when a request comes in. The messy bit is passing the  
> > stdin/stdout/stderr file descriptors over a socket. And it could be  
> > called “railgun” 🙂
> 
> It turns out all the messy passing of IO objects is already included in  
> the Ruby standard socket library, so without further ado, here’s a  
> working proof-of-concept 🙂 Tested under ruby 1.8.6p111

This is essentially the magic behind Passenger, which also manages the  
child processes and balances requests across them. So yeah, it’s doable  
and not too peculiar.

- Charlie

---

<div class="post-metadata">

**Author:** ![headius](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/7c8e57/32.png) [@headius](https://www.ruby-forum.com/u/headius)\
**Post date:** [May 15, 2009, 4:58pm UTC](https://www.ruby-forum.com/t/jruby-1-3-0-will-include-nailgun/167919/9 "2009-05-15T16:58:43Z")

</div>

Brian C. wrote:

> However, don’t get too excited - it doesn’t play particularly well with  
> Rails yet. In particular, “frake test:units” doesn’t run any tests.

I’ve fixed that, and a number of other issues, and now it actually plays  
rather well with Rails.

The new code detects that you are using rails and start multiple  
processes, one for each environment of interest (by default ‘test’ and  
‘development’), so that you can have a near-instant startup for either  
purpose.
