Compile and execute ruby script at runtime?

Hello,

I have written a DSL using Ruby that I run on my JBoss server(s).
Currently I load a ScriptEngine using “JRuby” and execute the script
(which is stored in the DB). This is running horribly slow and I’m
looking at ways to improve it. The Ruby script calls Java and it looks
like the Ruby->Java interface is really slow when running via
ScriptEngine.

One thing I’m considering is compiling the script at runtime and
executing the resulting code directly; this allows me to remove
ScriptEngine altogether. Is this possible? I’d rather not compile all
the scripts pre-runtime because that prevents me from updating the
scripts (in the DB) and reloading them on the server without restarting
the server.

Thanks

DG -

Can you be more specific as to exactly what is slow? Are you sure it’s
the JRuby interpretation of the code? Can you tell us more about what
the code’s doing, and what kind of Ruby ↔ Java interop there is? Is
it calling something in Java many times? Etc…

In case you’re not already familiar with it, Ruby’s benchmarking is
helpful and very easy to use (see
Module: Benchmark (Ruby 1.9.3)).

  • Keith

On Thu, Oct 18, 2012 at 12:33 PM, DG Christensen [email protected]
wrote:

I have written a DSL using Ruby that I run on my JBoss server(s).
Currently I load a ScriptEngine using “JRuby” and execute the script
(which is stored in the DB). This is running horribly slow and I’m
looking at ways to improve it. The Ruby script calls Java and it looks
like the Ruby->Java interface is really slow when running via ScriptEngine.

Under some modes in some versions of JRuby, ScriptEngine will disable
our internal JIT compilation. That may be why things are slower than
you expect.

One thing I’m considering is compiling the script at runtime and
executing the resulting code directly; this allows me to remove
ScriptEngine altogether. Is this possible? I’d rather not compile all
the scripts pre-runtime because that prevents me from updating the
scripts (in the DB) and reloading them on the server without restarting
the server.

That’s certainly an option. There are a few articles on the wiki about
generating “normal” Java classes you can call directly as long as
JRuby’s present in classpath.

  • Charlie

Thanks for your response Keith.

I don’t have any hard data to show you, unfortunately. My DSL is
basically a ruby wrapper around Java classes and most of the work is
done in Java. When I first started I had a lot of loops written in Ruby
that called Java inside the loop. At this time my Ruby scripts were
taking 10-12 seconds to run. My first optimization was to write helper
methods in Java that performed the loops, which were called from Ruby.
I.e. same amount of work in the end but a lot fewer Ruby->Java calls.
This cut the runtime down by about half but still not good enough.

My latest optimization was to precompile the scripts into Java objects
as detailed here:
DirectJRubyEmbedding · jruby/jruby Wiki · GitHub. I also set
the JRuby JIT threshold to 0. The objects are then cached for later
use. This got my execute time down to under a second which is good
enough for now.