Ich benutze Java 8 Nashorn, um CommonMark HTML-Server-Seite zu rendern. Wenn ich eine CompiledScript
kompiliere und zwischenspeichern und wiederverwende, dauert die Wiedergabe einer bestimmten Seite 5 Minuten. Wenn ich stattdessen eval
verwende und die Skript-Engine zwischenspeichern und wiederverwende, dauert das Rendern derselben Seite 3 Sekunden.Wie macht Java 8 Nashorn schnell?
Warum ist CompiledScript
so langsam? (Beispielcode folgt)
Was ist ein guter Ansatz für die Ausführung von Javascript-Code in Nashorn, immer wieder so schnell wie möglich? Und vermeiden, den Javascript-Code mehr als einmal zu kompilieren?
Dies ist das serverseitige Scala-Code-Snippet, das Nashorn in einer Weise aufruft, die 5 Minuten dauert: (wenn 200 Mal ausgeführt; Ich erstelle viele Kommentare von CommonMark zu HTML.) (Dieser Code basiert auf 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()
bearbeiten Beachten Sie, dass die $script
über 200 mal neu bewertet wird. Ich habe eine Version getestet, die es nur einmal ausgewertet hat, aber anscheinend habe ich dann einen Bug geschrieben, weil die einzige Version nicht schneller als 5 Minuten war, obwohl sie eine der schnellsten sein sollte, see Halfbit's answer. Hier ist die schnelle Version:
...
val newCompiledScript = newEngine.asInstanceOf[js.Compilable].compile(s"""
var global;
var remarkable;
if (!remarkable) {
global = this;
$script;
remarkable = new Remarkable({});
}
remarkable.render(__source__);""")
...
/bearbeiten
Während dieser 2,7 Sekunden dauert: (wenn 200-mal laufen)
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)")
Ich hätte eigentlich gedacht, dass die CompiledScript
Version (die oberste Schnipsel) wäre schneller gewesen. Wie auch immer, ich werde wohl die Seite des gerenderten HTML-Servers zwischenspeichern müssen.
(Linux Mint 17 & Java 8 u20)
Update:
Ich habe gerade bemerkt, dass invokeFunction
am Ende statt eval
mit fast doppelt so schnell ist, dauert nur 1,7 Sekunden. Das ist ungefähr so schnell wie meine Java 7-Version, die Javascript-Code verwendet, der von Rhino zu Java-Bytecode kompiliert wurde (als separater und komplizierter Schritt im Build-Prozess). Vielleicht ist das so schnell wie es geht?
Ich habe auch Nashorn gefunden, um langsamer als Nashorn zu sein http://softwarecenturion.me/posts/2014-04-07-jdk8-nashorn-performance/. Es wird viel schneller mit warmem JIT, aber es ist unbrauchbar langsam kalt. Ich bin auch neugierig, ob du irgendetwas dagegen tun kannst. – coudy