如何使Java 8 Nashorn快速
How make Java 8 Nashorn fast?
我使用Java 8 Nashorn将CommonMark呈现到HTML服务器端。如果我编译、缓存并重用CompiledScript
,那么某个页面需要5分钟才能呈现。但是,如果我改为使用eval
,并缓存和重用脚本引擎,则呈现同一页面需要3秒。
为什么CompiledScript
这么慢?(示例代码如下)
在Nashorn中一遍又一遍地快速运行Javascript代码的好方法是什么?避免多次编译Javascript代码?
这是服务器端Scala代码片段,它以一种需要5分钟的方式调用Nashorn:(当运行200次时;我正在将许多注释从CommonMark编译为HTML。)(此代码基于这篇博客文章。)
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分钟,尽管它应该是最快的版本之一,请参阅Halfbit的答案。这是快速版本:
...
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秒。这大约和我的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
的代码变体似乎对remarkable.min.js
进行了200次重新评估,而基于eval
的版本只进行了一次评估。这就解释了运行时的巨大差异。
只预编译了remarkable.render(__source__)
,基于CompiledScript
的变体比基于eval
和invokeFunction
的变体(在我的机器Oracle Java 8u25上)稍微快一些。
CompiledScript在8u40中得到了一些改进。您可以下载jdk8u40@的早期访问下载https://jdk8.java.net/download.html
- keyup事件处理程序更改焦点不适用于快速键入
- jquery快速悬停问题
- d3-js快速事件调用问题
- 快速排序程序未正确输出
- 使用javascript和随机暂停/超时快速循环文本
- firebase中有没有一种方法可以防止快速连续写入
- 扩展Nashorn-ecma引擎以添加新的运算符和类型
- Angular JS-如何强制浏览器记录历史以便快速路由
- 有可能通过sessionID获得快速会话吗
- 将toString方法暴露给nashorn中的js对象
- 如何在快速选项卡式面板中禁用选项卡单击
- 编辑CSV数组中的项目-快速CSV node.js
- JavaScript数组的子类化破坏了快速枚举
- 节点.js快速删除 req.body 不起作用
- 使用cordova快速nodejs socket.io
- 将普通js转换为角度语法的快速方法
- 快速的套接字 io 实例/中间件
- 如果鼠标在元素上快速移动和关闭,则防止.hoop事件被垃圾邮件发送
- 谷歌图表-“;快速入门Hello World;不在IE8中渲染
- 如何使Java 8 Nashorn快速