java javascript performance nashorn

¿Cómo hacer rápido Java 8 Nashorn?



javascript performance (2)

Estoy usando Java 8 Nashorn para renderizar CommonMark al lado del servidor HTML. Si compilo y guardo en caché y reutilizo un CompiledScript , una página determinada tarda 5 minutos en procesarse. Sin embargo, si en su lugar utilizo eval , y caché y reutilizo el motor de script, la representación de la misma página tarda 3 segundos.

¿Por qué es tan lento CompiledScript ? (código de ejemplo sigue)

¿Cuál es un buen enfoque para ejecutar el código Javascript en Nashorn, una y otra vez lo más rápido posible? ¿Y evitando compilar el código Javascript más de una vez?

Este es el fragmento de código Scala del lado del servidor que llama a Nashorn de una manera que toma 5 minutos: (cuando se ejecuta 200 veces, estoy compilando muchos comentarios de CommonMark a HTML) (este código se basa en este artículo del blog ).

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()

Editar Tenga en cuenta que el $script arriba se vuelve a evaluar 200 veces. Probé una versión que la evaluó solo una vez, pero aparentemente luego escribí un error, porque la única versión no fue más rápida que 5 minutos, aunque debería haber sido una de las más rápidas, vea la respuesta de Halfbit . Aquí está la versión rápida:

... val newCompiledScript = newEngine.asInstanceOf[js.Compilable].compile(s""" var global; var remarkable; if (!remarkable) { global = this; $script; remarkable = new Remarkable({}); } remarkable.render(__source__);""") ...

/Editar

Mientras que esto toma 2.7 segundos: (cuando se ejecuta 200 veces)

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)")

En realidad, habría adivinado que la versión de CompiledScript (el fragmento de código superior) habría sido más rápida. De todos modos, supongo que tendré que guardar en caché el lado del servidor HTML representado.

(Linux Mint 17 y Java 8 u20)

Actualizar:

Acabo de notar que usar invokeFunction al final en lugar de eval es casi el doble de rápido, toma solo 1.7 segundos. Esto es aproximadamente tan rápido como mi versión de Java 7 que usaba el código Javascript compilado por Rhino en el código de bytes de Java (como un paso separado y complicado en el proceso de compilación). Tal vez esto es lo más rápido que puede conseguir?

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**")



La variante de su código que utiliza CompiledScript parece volver a evaluar remarkable.min.js 200 veces, mientras que su versión basada en eval hace esto una vez. Esto explica la gran diferencia en tiempos de ejecución.

Con solo el remarkable.render(__source__) precompilado, la variante basada en CompiledScript es ligeramente más rápida que las basadas en eval e invokeFunction (en mi máquina, Oracle Java 8u25).