如何使Java8Nashorn快速?
我使用Java8Nashorn渲染到HTML服务器端。如果我编译、缓存并重用如何使Java8Nashorn快速?,java,javascript,performance,nashorn,Java,Javascript,Performance,Nashorn,我使用Java8Nashorn渲染到HTML服务器端。如果我编译、缓存并重用编译脚本,则渲染某个页面需要5分钟。但是,如果我改为使用eval,缓存并重用脚本引擎,则渲染同一页面需要3秒钟 为什么CompiledScript这么慢?(示例代码如下) 在Nashorn中一次又一次地尽可能快地运行Javascript代码的好方法是什么?避免多次编译Javascript代码 这是服务器端Scala代码段,它以5分钟的时间调用Nashorn:(当运行200次时;我正在将许多注释从CommonMark编译为
编译脚本
,则渲染某个页面需要5分钟。但是,如果我改为使用eval
,缓存并重用脚本引擎,则渲染同一页面需要3秒钟
为什么CompiledScript
这么慢?(示例代码如下)
在Nashorn中一次又一次地尽可能快地运行Javascript代码的好方法是什么?避免多次编译Javascript代码
这是服务器端Scala代码段,它以5分钟的时间调用Nashorn:(当运行200次时;我正在将许多注释从CommonMark编译为HTML。)(此代码基于。)
编辑注意上面的$script
被重新评估了200次。我确实测试了一个只评估过一次的版本,但很明显,后来我写了一些bug,因为只有一次的版本不会超过5分钟,尽管它应该是最快的版本之一。以下是快速版本:
...
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次时)
实际上,我猜CompiledScript
版本(最上面的代码片段)会更快。无论如何,我想我必须缓存呈现的HTML服务器端
(Linux Mint 17和Java 8 u20)
更新:
我刚刚注意到,在末尾使用invokeFunction
而不是eval
的速度几乎是原来的两倍,只需1.7秒。这大概和我的Java7版本一样快,该版本使用Rhino编译的Javascript代码转换成Java字节码(作为构建过程中一个独立而复杂的步骤)。也许这是最快的速度了
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在8u40中有了一些改进。您可以下载jdk8u40@的早期访问下载使用
CompiledScript
的代码变体似乎重新评估了signific.min.js
200次,而基于eval
的版本只执行一次。这解释了运行时的巨大差异
只需预先编译
引人注目的.render(
source),基于CompiledScript
的变体比基于eval
和invokeffunction
的变体(在我的机器上,Oracle Java 8u25)稍微快一些。我还发现nashorn比rhino慢。在温暖的JIT中速度会快得多,但在寒冷中速度却慢得无法忍受。同样好奇的是,你是否能对此做些什么。不过,这并不能真正回答问题。这似乎就是解释。我确实测试了一个替代方案,该方案没有多次重新评估引人注目的.min.js
,但发现它也需要5分钟,因此我没有将其包括在问题中。然而,我一定犯了一些错误(即意外地将变量重置为null,而不是仅仅声明它),因为现在当我再次测试一个未重新评估非凡.min.js的编译脚本时,它的速度大致与fasteval
版本一样快(不知道我的计算机上哪一个最快).我用fastCompiledScript
版本更新了这个问题-我希望它与您使用的版本大致相同?我觉得有点不确定Nashorn在随后的eval
调用后会记住哪些变量,但显然它确实会记住顶级变量,如global
和spective
。实际上,我只是预编译了spective.render(\uu source\uuu)
。所有顶级脚本变量最终都在引擎范围内,并被每个eval
重新使用(并最终修改),无论是否预编译。(我实际验证了在使用eval和预编译变量执行脚本后绑定是相等的。)
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)")
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**")