我正在使用Java 8 Nashorn将CommonMark呈现到HTML服务器端。如果我编译和缓存并重用CompiledScript
,则某个页面需要5分钟的渲染时间。但是,如果我改用eval
,并缓存并重用脚本引擎,则呈现同一页面需要3秒钟。
为什么CompiledScript
这么慢? (示例代码如下)
在Nashorn中一次又一次地运行Javascript代码的一种好方法是什么?并避免多次编译Javascript代码?
这是服务器端Scala代码片段,以5分钟的时间调用Nashorn :(运行200次;我正在将许多注释从CommonMark编译为HTML。)(此代码基于this blog article。)
if (engine == null) {
val script = scala.io.Source.fromFile("public/res/remarkable.min.js").mkString
engine = new js.ScriptEngineManager(null).getEngineByName("nashorn")
compiledScript = engine.asInstanceOf[js.Compilable].compile(s"""
var global = this;
$script;
remarkable = new Remarkable({});
remarkable.render(__source__);""");
}
engine.put("__source__", "**bold**")
val htmlText = compiledScript.eval()
编辑请注意,上面的
$script
重新评估了200次。我确实测试了一个只能评估一次的版本,但显然然后我写了一个错误,因为单次版本的速度不超过5分钟,尽管它应该是最快的版本之一see Halfbit's answer。这是快速版本:...
val newCompiledScript = newEngine.asInstanceOf[js.Compilable].compile(s"""
var global;
var remarkable;
if (!remarkable) {
global = this;
$script;
remarkable = new Remarkable({});
}
remarkable.render(__source__);""")
...
/编辑
而这需要2.7秒:(运行200次时)
if (engine == null) {
engine = new js.ScriptEngineManager(null).getEngineByName("nashorn")
engine.eval("var global = this;")
engine.eval(new jio.FileReader("public/res/remarkable.min.js"))
engine.eval("remarkable = new Remarkable({});")
}
engine.put("source", "**bold**")
val htmlText = engine.eval("remarkable.render(source)")
我实际上已经猜到
CompiledScript
版本(最上面的代码段)会更快。无论如何,我想我必须缓存呈现的HTML服务器端。(Linux Mint 17和Java 8 u20)
更新:
我只是注意到,最后使用
invokeFunction
而不是eval
几乎快一倍,仅需1.7秒。这与使用Rhino编译为Java字节码的Javascript代码的Java 7版本(作为构建过程中一个单独且复杂的步骤)的速度差不多。也许这是最快的吗?if (engine == null) {
engine = new js.ScriptEngineManager(null).getEngineByName("nashorn")
engine.eval("var global = this;")
engine.eval(new jio.FileReader("public/res/remarkable.min.js"))
engine.eval("remarkable = new Remarkable({});")
engine.eval(
"function renderCommonMark(source) { return remarkable.render(source); }")
}
val htmlText = engine.asInstanceOf[js.Invocable].invokeFunction(
"renderCommonMark", "**bold1**")
最佳答案
您使用CompiledScript
的代码变体似乎重新评估了remarkable.min.js
200次-而基于eval
的版本仅对此进行了一次评估。这解释了运行时的巨大差异。
仅预编译了remarkable.render(__source__)
,基于CompiledScript
的变体比基于eval
和invokeFunction
的变体要快一些(在我的机器上是Oracle Java 8u25)。