Optimize startup initialization


#1

Hello,

I’ve been successfully using JRuby from within Java for some time and
now I’m trying to improve the startup time. The code is available as an
open source project called LESS Engine [1] and wraps a cool Ruby library
for CSS called LESS [2].

Here is the test code I’m currently using:

List loadPaths = new ArrayList();
loadPaths.add(“META-INF/jruby.home/lib/ruby/site_ruby/1.8”);
loadPaths.add(“META-INF/less/lib”);
loadPaths.add(“META-INF/mutter/lib”);
loadPaths.add(“META-INF/polyglot/lib”);
loadPaths.add(“META-INF/treetop/lib”);

runtime = JavaEmbedUtils.initialize(loadPaths); // takes 2852ms
adapter = JavaEmbedUtils.newRuntimeAdapter(); // takes 1ms
adapter.eval(runtime, “require ‘less’”); // takes 7893ms
adapter.eval(runtime, "require ‘less’ \nLess::Engine.new('div { width: 1

  • 1 }’).to_css"); // 39ms

After the first eval() everything runs smoothly. Any ideas how the above
can be optimized are welcome.

I’m running the test using JRuby 1.4 and Maven 2.2.1. My Java version
is:

Java™ SE Runtime Environment (build 1.6.0_17-b04-248-9M3125)
Java HotSpot™ 64-Bit Server VM (build 14.3-b01-101, mixed mode)

Thanks!

[1] http://github.com/asual/lesscss-engine
[2] http://github.com/cloudhead/less


#2

Hi

On Thu, Jan 21, 2010 at 5:22 PM, Rostislav Hristov
removed_email_address@domain.invalid wrote:

loadPaths.add(“META-INF/jruby.home/lib/ruby/site_ruby/1.8”);

After the first eval() everything runs smoothly. Any ideas how the above
can be optimized are welcome.

JavaEmbedUtils.initialize() instantiates Ruby runtime. This takes long
time and, now, Charlie, Vlad and other couple of people have been
trying to cut down the runtime initialization time. You can expect
shorter time on JRuby 1.5.0.
The difference of two eval()s’ time comes from JRuby’s library cache
mechanism. The first “require ‘less’” actually loads the library,
which is a bit cumbersome job and takes much time. But, once the
library has been loaded, JRuby doesn’t load the same library again.
This means the second “require ‘less’” does almost nothing. Probably,
you don’t need “require ‘less’” in the second eval(). Did you try
that? I think Charlie did (or tried to do) something to cut down
library loading time.

FYI:
If you use JRuby Embed (Red Bridge) API, you can write above code like
this:

ScriptingContainer container = new ScriptingContainer();
container.setLoadPath(loadPaths); // JRuby 1.5.0
//container.getProvider().setLoadPaths(loadPaths); // JRuby 1.4.0
container.runScriptlet(“require ‘less’ \nLess::Engine.new(‘div {
width: 1 > + 1 }’).to_css”);

See http://kenai.com/projects/jruby/pages/RedBridge for details.

-Yoko


To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email

#3

Thanks, Yoko!

The initialization takes about 3 seconds and I think I can live with
that. After the first require everything runs fast and the removal of
the latter require statements probably will make a slight difference.
Before posting I tried JRuby Embed with JRuby 1.4 and I think I got an
error and similar time results.

Is there a way to prepare the Ruby libraries in a format that makes
loading them in JRuby faster? I suppose that internally they are
initially parsed and converted into something different from plain code?

Are there JRuby 1.5 Maven artifacts available somewhere so I can easily
start playing with it?

Thanks again!


#4

Is there a way to prepare the Ruby libraries in a format that makes
loading them in JRuby faster? I suppose that internally they are
initially parsed and converted into something different from plain code?

are you on windows?
-r


#5

On Fri, Jan 22, 2010 at 7:00 AM, Rostislav Hristov
removed_email_address@domain.invalid wrote:

The initialization takes about 3 seconds and I think I can live with
that. After the first require everything runs fast and the removal of
the latter require statements probably will make a slight difference.
Before posting I tried JRuby Embed with JRuby 1.4 and I think I got an
error and similar time results.

You can probably get better performance with embedding API of JRuby
1.5 than 1.4 since I changed some internal behaviors.

Is there a way to prepare the Ruby libraries in a format that makes
loading them in JRuby faster? I suppose that internally they are
initially parsed and converted into something different from plain code?

I don’t think we have a relevant way to make library loading faster.
JRuby’s jit options might work, but I’m not sure.

Are there JRuby 1.5 Maven artifacts available somewhere so I can easily
start playing with it?

It’s not yet in maven repo. But, if you have JRuby trunk, you can
install it in your local repo by

git clone git://kenai.com/jruby~main
cd jruby~main
mvn install

-Yoko

http://xircles.codehaus.org/manage_email


To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email

#6

On Sat, Jan 23, 2010 at 8:23 AM, Rostislav Hristov
removed_email_address@domain.invalid wrote:

ScriptingContainer container = new ScriptingContainer(); // 328ms
container.setLoadPaths(loadPaths); // 0ms
container.runScriptlet(“require ‘less’”); // 8741ms
container.runScriptlet(“Less::Engine.new(‘div { width: 1 + 1
}’).to_css”); //94ms

The instantiation is about 8x faster. The other operations are a little
bit slower but this may have something to do with the current state of
my computer. I’m using OS X 10.5.8 (MBP 2.4GHz with 4GB DDR2 RAM).

The instantiation of ScriptingContainer should be way faster since it
doesn’t instantiate Ruby runtime. :wink: ScriptingContainer delays runtime
initialization as much as possible. In the code above, the first
runScriptlet() created Ruby runtime, also, loaded the library. Two big
jobs were done in a single evaluation, so took much time. However the
performance seemed to be improved. The reason of slower evaluation
than old API is JRuby Embed does more for sharing variables. You might
get better performance if you do container.clear() right after the
runScriptlet method.

JRuby 1.5 currently doesn’t load classpath resources in the same way
like 1.4. Please, notice how I changed the library paths in order to
make it work. Is there a schedule for the next release?

I think this comes from the change of library loading. JRuby Embed had
a little change to set load paths, but it shouldn’t affect the way of
seeing paths. Anyways, it’s a good information for embedders.

The JRuby Embed API is definitely nicer than the one I used before. Is
there something like JavaEmbedUtils.terminate(runtime) and is it
required?

In every evaluation, either runScriptlet or eval method,
JavaEmbedUtils.terminate gets run, so you don’t need to do by
yourself.

-Yoko


To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email

#7

Here are the results using JRuby 1.5 and JRuby Embed 0.1.3 both built
out of the latest development sources:

ClassLoader loader = getClass().getClassLoader();
List loadPaths = new ArrayList();
loadPaths.add(“META-INF/jruby.home/lib/ruby/site_ruby/1.8”);
loadPaths.add(loader.getResource(“META-INF/less/lib”).getPath());
loadPaths.add(loader.getResource(“META-INF/mutter/lib”).getPath());
loadPaths.add(loader.getResource(“META-INF/polyglot/lib”).getPath());
loadPaths.add(loader.getResource(“META-INF/treetop/lib”).getPath());

ScriptingContainer container = new ScriptingContainer(); // 328ms
container.setLoadPaths(loadPaths); // 0ms
container.runScriptlet(“require ‘less’”); // 8741ms
container.runScriptlet(“Less::Engine.new(‘div { width: 1 + 1
}’).to_css”); //94ms

The instantiation is about 8x faster. The other operations are a little
bit slower but this may have something to do with the current state of
my computer. I’m using OS X 10.5.8 (MBP 2.4GHz with 4GB DDR2 RAM).

JRuby 1.5 currently doesn’t load classpath resources in the same way
like 1.4. Please, notice how I changed the library paths in order to
make it work. Is there a schedule for the next release?

The JRuby Embed API is definitely nicer than the one I used before. Is
there something like JavaEmbedUtils.terminate(runtime) and is it
required?

Any other ideas for optimization are welcome. Thanks!