title: How make Java 8 Nashorn fast?
body: <p>I'm using Java 8 Nashorn to render <a href="http://commonmark.org/" rel="nofollow noreferrer">CommonMark</a> to HTML server side. If I compile and cache and reuse a <code>CompiledScript</code>, a certain page takes 5 minutes to render. However, if I instead use <code>eval</code>, and cache and reuse the script engine, rendering the same page takes 3 seconds.</p>
  
  <p>Why is <code>CompiledScript</code> so slow? (sample code follows)</p>
  
  <p>What's a good approach for running Javascript code in Nashorn, over and over again as quickly as possible? And avoiding compiling the Javascript code more than once?</p>
  
  <p>This is the server side Scala code snippet that calls Nashorn in a way that takes 5 minutes: (when run 200 times; I'm compiling many comments from CommonMark to HTML.) (This code is based on <a href="http://blog.javabien.net/2014/02/19/use-nashorn-and-webjars-to-execute-javascript-server-side/" rel="nofollow noreferrer">this blog article</a>.)</p>
  
  <pre><code>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()
  </code></pre>
  
  <p><strong>Edit</strong> Note that the <code>$script</code> above is reevaluated 200 times. I did test a version that evaluated it only once, but apparently then I wrote some bug, because the only-once version wasn't faster than 5 minutes, although it should have been one of the fastest ones, <a href="https://stackoverflow.com/a/26577661/694469">see Halfbit's answer</a>. Here's the fast version:</p>
  
  <pre><code>...
  val newCompiledScript = newEngine.asInstanceOf[js.Compilable].compile(s"""
    var global;
    var remarkable;
    if (!remarkable) {
      global = this;
      $script;
      remarkable = new Remarkable({});
    }
    remarkable.render(__source__);""")
  ...
  </code></pre>
  
  <p><strong>/Edit</strong></p>
  
  <p>Whereas this takes 2.7 seconds: (when run 200 times)</p>
  
  <pre><code>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)")
  </code></pre>
  
  <p>I would actually have guessed that the <code>CompiledScript</code> version (the topmost snippet) would have been faster. Anyway, I suppose I'll have to cache the rendered HTML server side.</p>
  
  <p>(Linux Mint 17 &amp; Java 8 u20)</p>
  
  <p><strong>Update:</strong></p>
  
  <p>I just noticed that using <code>invokeFunction</code> at the end instead of <code>eval</code> is almost twice as fast, takes only 1.7 seconds. This is roughly as fast as my Java 7 version that used Javascript code compiled by Rhino to Java bytecode (as a separate and complicated step in the build process). Perhaps this is as fast as it can get?</p>
  
  <pre><code>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**")
  </code></pre>