首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何让Java 8 Nashorn变得更快?

如何让Java 8 Nashorn变得更快?
EN

Stack Overflow用户
提问于 2014-10-25 18:13:31
回答 2查看 11.5K关注 0票数 19

我使用Java8Nashorn将CommonMark呈现到HTML服务器端。如果我编译、缓存和重用一个CompiledScript,某个页面需要5分钟才能呈现。但是,如果我改用eval,并缓存和重用脚本引擎,渲染相同的页面需要3秒钟。

为什么CompiledScript这么慢?(示例代码如下)

在Nashorn中一遍又一遍、尽可能快地运行Javascript代码的好方法是什么?并避免多次编译Javascript代码?

这是服务器端的Scala代码片段,它以5分钟的方式调用Nashorn:(当运行200次时,我将许多注释从CommonMark编译为HTML.)(此代码基于this blog article。)

代码语言:javascript
复制
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次。我确实测试了一个只评估了一次的版本,但显然后来我写了一些bug,因为只有一次的版本不会超过5分钟,尽管它应该是最快的版本之一,see Halfbit's answer。以下是快速版本:

代码语言:javascript
复制
...
val newCompiledScript = newEngine.asInstanceOf[js.Compilable].compile(s"""
  var global;
  var remarkable;
  if (!remarkable) {
    global = this;
    $script;
    remarkable = new Remarkable({});
  }
  remarkable.render(__source__);""")
...

/Edit

而这需要2.7秒:(当运行200次时)

代码语言:javascript
复制
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服务器端。

(LinuxMint17和Java8 u20)

更新:

我只是注意到在最后使用invokeFunction而不是eval几乎快了一倍,只需要1.7秒。这大致与我的Java7版本一样快,该版本使用由Rhino编译的Javascript代码转换为Java字节码(作为构建过程中一个单独且复杂的步骤)。也许这是它能得到的最快的速度?

代码语言:javascript
复制
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**")
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26561292

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档