Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

With Java ScriptEngine (Groovy), how to make it more performant?

I am using ScriptEngine in my app to evaluate some client code in my application. The problem is it's not performant enough and I need to take measures to improve the time of execution. Currently, it can take up to 1463ms (average is around 300ms) to eval an extremely simple script which is basically parameter replacement in URLs.

I'm looking for simple strategies to improve this performance without losing the scripting ability.

My first thought it to pool the ScriptEngine object and reuse it. I see in the spec it's meant to be reused but I haven't found any examples of anyone actually doing it.

Any ideas? Here is my code:

ScriptEngineManager factory = new ScriptEngineManager();
GroovyScriptEngineImpl engine = (GroovyScriptEngineImpl)factory.getEngineByName("groovy");
engine.put("state", state;
engine.put("zipcode", zip);
engine.put("url", locationAwareAd.getLocationData().getGeneratedUrl());
url = (String) engine.eval(urlGeneratorScript);

Any feedback would be appreciated!

like image 549
matsientst Avatar asked Aug 31 '12 17:08

matsientst


People also ask

What is Groovy JSR223?

Apache Groovy is the default scripting language for JSR223 Elements.

Why do we use Groovy?

Groovy is a scripting language with Java-like syntax for the Java platform. The Groovy scripting language simplifies the authoring of code by employing dot-separated notation, yet still supporting syntax to manipulate collections, Strings, and JavaBeans.


1 Answers

Most likely the problem is that the engine actually evaluates the script every time eval() is called. Instead, you could re-use the precompiled script via Compilable interface.

    // move this into initialization part so that you do not call this every time.
    ScriptEngineManager manager = new ScriptEngineManager();
    ScriptEngine engine  = manager.getEngineByName("groovy");
    CompiledScript script = ((Compilable) engine).compile(urlGeneratorScript);

    //the code below will use the precompiled script code
    Bindings bindings = new Bindings();
    bindings.put("state", state;
    bindings.put("zipcode", zip);
    bindings.put("url", locationAwareAd.getLocationData().getGeneratedUrl());
    url = script.eval(bindings);

FWIW, you can also implement the file timestamp check, if the script is changed call compile(..) again.

like image 139
Anton Arhipov Avatar answered Sep 21 '22 09:09

Anton Arhipov