I have a Java application that depends on the result from a ruby script. The issue I'm facing is that this ruby script is called many times which requires loading the script's libraries every time it's executed.
I'm not familiar with Ruby, but in my search I've come across JRuby. Since it interprets ruby code and runs it on the JVM, my initial thought was "great, I can just compile the ruby script to .class files package it up and interact with it like regular java objects". This would avoid the overhead that came with loading the libraries each time I executed the ruby script.
After looking deeper into jruby, I'm understanding it doesn't work this way. So to do what I want I can use JRuby's JavaEmbedUtils to
- Load a Ruby runtime object with my ruby scripts
- Create a receiver object that essentially knows how to handle and respond to my script.
- Invoke the desired method from script.
This is what I had in mind (I'll be testing soon)
// 1
List<String> paths = new ArrayList<>();
paths.add(".");
Ruby runtime = JavaEmbedUtils.initialize(paths);
// 2
String script = "/path/to/script.rb";
IRubyObject recvr = JavaEmbedUtils.newRuntimeAdapter().eval(runtime, script);
// 3 Call this many times
JavaEmbedUtils.invokeMethod(runtime, receiver, "method", null, null);
Is my understanding correct in that this approach allows me to use the contents of the script many times while loading the script's libraries once? Is there an alternate or more JRuby way of doing what i'm looking for?
UPDATE
So I tested something similar to what Eugene suggested (a) i.e. ScriptingContainer and compared that to calling the script using (b) java.lang.Runtime for a total of 30 runs.
- On average, (a) was about 8x faster (b)
- Initializing (a)'s runtime took about 7 seconds
- The initial run for both (a) & (b) took 40x & 150-250x longer than following runs.
- (a)'s initial run was 11x faster than (b)s