如何使Java 8 Nashorn快?

我使用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()

编辑注意上面的$脚本被重新评估了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编译的JavaScript代码到Java字节码(作为构建过程中单独和复杂的步骤)的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的代码变体似乎重新评估卓越的.min.js 200次 – 而您的基于eval的版本会这样做一次。这解释了运行时的巨大差异。

只需要预编译的显着的(__ source__),基于CompiledScript的变体比基于eval和invokeFunction的变体稍微快一些(在我的机器上,Oracle Java 8u25)。

http://stackoverflow.com/questions/26561292/how-make-java-8-nashorn-fast

本站文章除注明转载外,均为本站原创或编译
转载请明显位置注明出处:如何使Java 8 Nashorn快?