使用Java ScriptEngine(Groovy),如何使其更具性能?

12

我的应用程序中使用ScriptEngine来评估一些客户端代码。问题在于它的性能不够好,我需要采取措施来提高执行时间。目前,即使是对URL进行参数替换这种极简单的脚本,也可能花费长达1463ms的时间(平均约为300ms)。

我正在寻找简单的策略来提高性能,同时又不失脚本能力。

我的第一个想法是池化ScriptEngine对象并重用它。在规范中看到它是可以被重复使用的,但我没有找到任何实际使用它的例子。

有什么想法吗? 这是我的代码:

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);

任何反馈将不胜感激!

1个回答

12

很可能的问题是每次调用eval()时,引擎实际上会重新评估脚本。相反,您可以通过Compilable接口重复使用预编译的脚本。

    // 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);

顺带一提,如果脚本被修改了,你也可以实现文件时间戳检查,然后再调用compile(..)。


哦,这是个好主意!我已经使用commons-pool池化了ScriptEngine。现在我会继续预编译。谢谢! - matsientst
1
似乎CompiledScript对于Groovy不会有任何影响,它只是调用engine.eval()方法 https://github.com/apache/groovy/blob/97c653d238567419f022d618ca1e5e804f147771/subprojects/groovy-jsr223/src/main/java/org/codehaus/groovy/jsr223/GroovyCompiledScript.java#L72 - Jarod

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接