<div dir="ltr">Thanks Rony & Ben,<br>Using JavaFX is an interesting idea, but that is a huge change for us and not the first choice at this point in time.<br><br>Spent some more time in optimizing the Nashorn engine itself ( forgetting licensing issues for a bit; I think that is worth a separate issue as such  ) . <br>Converting  <a href="https://github.com/openjdk/nashorn/blob/main/src/org.openjdk.nashorn/share/classes/org/openjdk/nashorn/internal/runtime/Context.java#L387">Context.ClassCache</a> into a global cache will share the code-cache  across threads; as simple as making it static. We may need to make other parts of ClassCache as thread safe as well <br>Do you see any issue in making <a href="https://github.com/openjdk/nashorn/blob/main/src/org.openjdk.nashorn/share/classes/org/openjdk/nashorn/internal/runtime/Context.java#L387">Context.ClassCache</a> as global cache. <br><br>Really appreciate your help.<br><br>thanks<br>Sakkanan<br><br><br>Here is the decompile 'script' class for reference<br>==============================<br><pre style="font-family:Menlo,courier;background-image:initial;background-position:initial;background-size:initial;background-repeat:initial;background-origin:initial;background-clip:initial"><span style="font-weight:bold;color:rgb(127,0,85)">package</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">org</span><span style="color:rgb(0,0,0)">.</span><span style="color:rgb(0,0,0)">openjdk</span><span style="color:rgb(0,0,0)">.</span><span style="color:rgb(0,0,0)">nashorn</span><span style="color:rgb(0,0,0)">.</span><span style="color:rgb(0,0,0)">internal</span><span style="color:rgb(0,0,0)">.</span><span style="color:rgb(0,0,0)">scripts</span><span style="color:rgb(0,0,0)">;</span><br><br><span style="font-weight:bold;color:rgb(127,0,85)">import</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">org</span><span style="color:rgb(0,0,0)">.</span><span style="color:rgb(0,0,0)">openjdk</span><span style="color:rgb(0,0,0)">.</span><span style="color:rgb(0,0,0)">nashorn</span><span style="color:rgb(0,0,0)">.</span><span style="color:rgb(0,0,0)">internal</span><span style="color:rgb(0,0,0)">.</span><span style="color:rgb(0,0,0)">runtime</span><span style="color:rgb(0,0,0)">.</span><span style="color:rgb(0,0,0)">PropertyMap</span><span style="color:rgb(0,0,0)">;</span><br><span style="font-weight:bold;color:rgb(127,0,85)">import</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">org</span><span style="color:rgb(0,0,0)">.</span><span style="color:rgb(0,0,0)">openjdk</span><span style="color:rgb(0,0,0)">.</span><span style="color:rgb(0,0,0)">nashorn</span><span style="color:rgb(0,0,0)">.</span><span style="color:rgb(0,0,0)">internal</span><span style="color:rgb(0,0,0)">.</span><span style="color:rgb(0,0,0)">runtime</span><span style="color:rgb(0,0,0)">.</span><span style="color:rgb(0,0,0)">ScriptFunction</span><span style="color:rgb(0,0,0)">;</span><br><span style="font-weight:bold;color:rgb(127,0,85)">import</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">org</span><span style="color:rgb(0,0,0)">.</span><span style="color:rgb(0,0,0)">openjdk</span><span style="color:rgb(0,0,0)">.</span><span style="color:rgb(0,0,0)">nashorn</span><span style="color:rgb(0,0,0)">.</span><span style="color:rgb(0,0,0)">internal</span><span style="color:rgb(0,0,0)">.</span><span style="color:rgb(0,0,0)">runtime</span><span style="color:rgb(0,0,0)">.</span><span style="color:rgb(0,0,0)">ScriptObject</span><span style="color:rgb(0,0,0)">;</span><br><span style="font-weight:bold;color:rgb(127,0,85)">import</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">org</span><span style="color:rgb(0,0,0)">.</span><span style="color:rgb(0,0,0)">openjdk</span><span style="color:rgb(0,0,0)">.</span><span style="color:rgb(0,0,0)">nashorn</span><span style="color:rgb(0,0,0)">.</span><span style="color:rgb(0,0,0)">internal</span><span style="color:rgb(0,0,0)">.</span><span style="color:rgb(0,0,0)">runtime</span><span style="color:rgb(0,0,0)">.</span><span style="color:rgb(0,0,0)">ScriptRuntime</span><span style="color:rgb(0,0,0)">;</span><br><span style="font-weight:bold;color:rgb(127,0,85)">import</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">org</span><span style="color:rgb(0,0,0)">.</span><span style="color:rgb(0,0,0)">openjdk</span><span style="color:rgb(0,0,0)">.</span><span style="color:rgb(0,0,0)">nashorn</span><span style="color:rgb(0,0,0)">.</span><span style="color:rgb(0,0,0)">internal</span><span style="color:rgb(0,0,0)">.</span><span style="color:rgb(0,0,0)">runtime</span><span style="color:rgb(0,0,0)">.</span><span style="color:rgb(0,0,0)">Source</span><span style="color:rgb(0,0,0)">;</span><br><br><span style="font-weight:bold;color:rgb(127,0,85)">public</span><span style="color:rgb(0,0,0)"> </span><span style="font-weight:bold;color:rgb(127,0,85)">class</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">Script$1$\</span><span style="color:rgb(0,0,0)">^</span><span style="color:rgb(0,0,0)">eval\_</span><span style="color:rgb(0,0,0)"> </span><span style="font-weight:bold;color:rgb(127,0,85)">extends</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">JS</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">{</span><br><span style="color:rgb(0,0,0)">  </span><span style="font-weight:bold;color:rgb(127,0,85)">private</span><span style="color:rgb(0,0,0)"> </span><span style="font-weight:bold;color:rgb(127,0,85)">static</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">Source</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">source</span><span style="color:rgb(0,0,0)">;</span><br><span style="color:rgb(0,0,0)">  </span><br><span style="color:rgb(0,0,0)">  </span><span style="font-weight:bold;color:rgb(127,0,85)">private</span><span style="color:rgb(0,0,0)"> </span><span style="font-weight:bold;color:rgb(127,0,85)">static</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">Object</span><span style="color:rgb(0,0,0)">[</span><span style="color:rgb(0,0,0)">]</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">constants</span><span style="color:rgb(0,0,0)">;</span><br><span style="color:rgb(0,0,0)">  </span><br><span style="color:rgb(0,0,0)">  </span><span style="font-weight:bold;color:rgb(127,0,85)">public</span><span style="color:rgb(0,0,0)"> </span><span style="font-weight:bold;color:rgb(127,0,85)">static</span><span style="color:rgb(0,0,0)"> </span><span style="font-weight:bold;color:rgb(127,0,85)">final</span><span style="color:rgb(0,0,0)"> </span><span style="font-weight:bold;color:rgb(127,0,85)">boolean</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">strictMode</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">=</span><span style="color:rgb(0,0,0)"> </span><span style="font-weight:bold;color:rgb(127,0,85)">false</span><span style="color:rgb(0,0,0)">;</span><br><span style="color:rgb(0,0,0)">  </span><br><span style="color:rgb(0,0,0)">  </span><span style="font-weight:bold;color:rgb(127,0,85)">public</span><span style="color:rgb(0,0,0)"> </span><span style="font-weight:bold;color:rgb(127,0,85)">static</span><span style="color:rgb(0,0,0)"> </span><span style="font-weight:bold;color:rgb(127,0,85)">boolean</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">:</span><span style="color:rgb(0,0,0)">program</span><span style="color:rgb(0,0,0)">(</span><span style="color:rgb(0,0,0)">ScriptFunction</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">:</span><span style="color:rgb(0,0,0)">callee</span><span style="color:rgb(0,0,0)">,</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">Object</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">:</span><span style="font-weight:bold;color:rgb(127,0,85)">this</span><span style="color:rgb(0,0,0)">)</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">{</span><br><span style="color:rgb(0,0,0)">    </span><span style="color:rgb(0,0,0)">ScriptObject</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">:</span><span style="color:rgb(0,0,0)">scope</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">=</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">:</span><span style="color:rgb(0,0,0)">callee</span><span style="color:rgb(0,0,0)">.</span><span style="color:rgb(0,0,0)">getScope</span><span style="color:rgb(0,0,0)">(</span><span style="color:rgb(0,0,0)">)</span><span style="color:rgb(0,0,0)">;</span><br><span style="color:rgb(0,0,0)">    </span><span style="color:rgb(0,0,0)">JO0P0</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">jO0P0</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">=</span><span style="color:rgb(0,0,0)"> </span><span style="font-weight:bold;color:rgb(127,0,85)">new</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">JO0P0</span><span style="color:rgb(0,0,0)">(</span><span style="color:rgb(0,0,0)">:</span><span style="color:rgb(0,0,0)">getMap</span><span style="color:rgb(0,0,0)">(</span><span style="color:rgb(0,0,0)">0</span><span style="color:rgb(0,0,0)">)</span><span style="color:rgb(0,0,0)">,</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">:</span><span style="color:rgb(0,0,0)">scope</span><span style="color:rgb(0,0,0)">)</span><span style="color:rgb(0,0,0)">;</span><br><span style="color:rgb(0,0,0)">    </span><span style="color:rgb(0,0,0)">:</span><span style="color:rgb(0,0,0)">scope</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">=</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">ScriptRuntime</span><span style="color:rgb(0,0,0)">.</span><span style="color:rgb(0,0,0)">mergeScope</span><span style="color:rgb(0,0,0)">(</span><span style="color:rgb(0,0,0)">(</span><span style="color:rgb(0,0,0)">ScriptObject</span><span style="color:rgb(0,0,0)">)</span><span style="color:rgb(0,0,0)">jO0P0</span><span style="color:rgb(0,0,0)">)</span><span style="color:rgb(0,0,0)">;</span><br><span style="color:rgb(0,0,0)">    </span><span style="font-weight:bold;color:rgb(127,0,85)">return</span><span style="color:rgb(0,0,0)"> </span><span style="font-weight:bold;color:rgb(127,0,85)">false</span><span style="color:rgb(0,0,0)">;</span><br><span style="color:rgb(0,0,0)">  </span><span style="color:rgb(0,0,0)">}</span><br><span style="color:rgb(0,0,0)">  </span><br><span style="color:rgb(0,0,0)">  </span><span style="font-weight:bold;color:rgb(127,0,85)">public</span><span style="color:rgb(0,0,0)"> </span><span style="font-weight:bold;color:rgb(127,0,85)">static</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">ScriptFunction</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">:</span><span style="color:rgb(0,0,0)">createProgramFunction</span><span style="color:rgb(0,0,0)">(</span><span style="color:rgb(0,0,0)">ScriptObject</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">paramScriptObject</span><span style="color:rgb(0,0,0)">)</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">{</span><br><span style="color:rgb(0,0,0)">    </span><span style="font-weight:bold;color:rgb(127,0,85)">return</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">ScriptFunction</span><span style="color:rgb(0,0,0)">.</span><span style="color:rgb(0,0,0)">create</span><span style="color:rgb(0,0,0)">(</span><span style="color:rgb(0,0,0)">constants</span><span style="color:rgb(0,0,0)">,</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">1</span><span style="color:rgb(0,0,0)">,</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">paramScriptObject</span><span style="color:rgb(0,0,0)">)</span><span style="color:rgb(0,0,0)">;</span><br><span style="color:rgb(0,0,0)">  </span><span style="color:rgb(0,0,0)">}</span><br><span style="color:rgb(0,0,0)">  </span><br><span style="color:rgb(0,0,0)">  </span><span style="font-weight:bold;color:rgb(127,0,85)">public</span><span style="color:rgb(0,0,0)"> </span><span style="font-weight:bold;color:rgb(127,0,85)">static</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">PropertyMap</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">:</span><span style="color:rgb(0,0,0)">getMap</span><span style="color:rgb(0,0,0)">(</span><span style="font-weight:bold;color:rgb(127,0,85)">int</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">paramInt</span><span style="color:rgb(0,0,0)">)</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">{</span><br><span style="color:rgb(0,0,0)">    </span><span style="font-weight:bold;color:rgb(127,0,85)">return</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">(</span><span style="color:rgb(0,0,0)">PropertyMap</span><span style="color:rgb(0,0,0)">)</span><span style="color:rgb(0,0,0)">constants</span><span style="color:rgb(0,0,0)">[</span><span style="color:rgb(0,0,0)">paramInt</span><span style="color:rgb(0,0,0)">]</span><span style="color:rgb(0,0,0)">;</span><br><span style="color:rgb(0,0,0)">  </span><span style="color:rgb(0,0,0)">}</span><br><span style="color:rgb(0,0,0)">  </span><br><span style="color:rgb(0,0,0)">  </span><span style="font-weight:bold;color:rgb(127,0,85)">public</span><span style="color:rgb(0,0,0)"> </span><span style="font-weight:bold;color:rgb(127,0,85)">static</span><span style="color:rgb(0,0,0)"> </span><span style="font-weight:bold;color:rgb(127,0,85)">void</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">:</span><span style="color:rgb(0,0,0)">setMap</span><span style="color:rgb(0,0,0)">(</span><span style="font-weight:bold;color:rgb(127,0,85)">int</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">paramInt</span><span style="color:rgb(0,0,0)">,</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">PropertyMap</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">paramPropertyMap</span><span style="color:rgb(0,0,0)">)</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">{</span><br><span style="color:rgb(0,0,0)">    </span><span style="color:rgb(0,0,0)">constants</span><span style="color:rgb(0,0,0)">[</span><span style="color:rgb(0,0,0)">paramInt</span><span style="color:rgb(0,0,0)">]</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">=</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">paramPropertyMap</span><span style="color:rgb(0,0,0)">;</span><br><span style="color:rgb(0,0,0)">  </span><span style="color:rgb(0,0,0)">}</span><br><span style="color:rgb(0,0,0)">}</span><br></pre><pre style="font-family:Menlo,courier;background-image:initial;background-position:initial;background-size:initial;background-repeat:initial;background-origin:initial;background-clip:initial"><span style="color:rgb(0,0,0)">===========</span></pre></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sat, Oct 26, 2024 at 7:50 AM Rony G. Flatscher <<a href="mailto:Rony.Flatscher@wu.ac.at">Rony.Flatscher@wu.ac.at</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><u></u>

  
    
  
  <div>
    <div>Just a somewhat "crazy" idea: it seems
      you are well acquainted with the details and if it turns out that
      Nashorn is not viable, how about trying to use JavaFX WebKit's
      JavaScript instead for your purposes? You may be able to implement
      a ScriptEngine for it that could better serve your needs? <br>
    </div>
    <div><br>
    </div>
    <div>You could check out the documentation
      of the JavaFX module javafx.web and take a look at its
      javafx.scene.web.WebEngine class as it documents its interfaces to
      JavaScript (note that this implementation mandates that WebEngine
      objects are created and accessed on the JavaFX Application/GUI
      thread only). </div>
    <div><br>
    </div>
    <div>If exploring that route, maybe the
      first thing to do is to ask about the viability of such an
      approach on the javafx mailing list (openjfx-dev mailing list of
      <a href="http://openjdk.org" target="_blank">openjdk.org</a>) first? <br>
    </div>
    <div><br>
    </div>
    <div>---rony</div>
    <p><br>
    </p>
    <div>On 26.10.2024 00:45, Packiaraj S wrote:<br>
    </div>
    <blockquote type="cite">
      
      <div dir="ltr">Thanks Ben. <br>
        I used visualVM just to compare CPU consumption between Java-11
        & Java 21. <br>
        Definitely spending more time using profilers will help to
        identify the issue but Nashorn's licensing (GPL v2) and
        inability to create Issue/PR in github repo makes me think if
        its a right direction towards the resolution of the issue.</div>
      <br>
      <div class="gmail_quote">
        <div dir="ltr" class="gmail_attr">On Fri, Oct 25, 2024 at
          2:50 PM Ben Evans <<a href="mailto:benjamin.john.evans@gmail.com" target="_blank">benjamin.john.evans@gmail.com</a>>
          wrote:<br>
        </div>
        <blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">You
          might try investigating further with a combination of JFR (JDK<br>
          Flight Recorder, built-in to the JDK) and the GUI tool JMC
          (JDK<br>
          Mission Control, available here: <a href="https://adoptium.net/en-GB/jmc/" rel="noreferrer" target="_blank">https://adoptium.net/en-GB/jmc/</a>)<br>
          <br>
          I often find it to be significantly more useful than the
          capabilities<br>
          of VisualVM.<br>
          <br>
          Thanks,<br>
          <br>
          Ben<br>
          <br>
          On Fri, Oct 25, 2024 at 4:21 PM Packiaraj S <<a href="mailto:s.packiaraj@gmail.com" target="_blank">s.packiaraj@gmail.com</a>>
          wrote:<br>
          ><br>
          > Hello,<br>
          ><br>
          > We use Nashorn with Tomcat as a long running service. We
          recently migrated to Java 21. ( from java 11 and the
          performance is good with Java-11).<br>
          > Since Nashorn is moved out of JDK we have pulled in
          'nashorn-core-15.4.jar' and its dependency (asm*) and loaded
          it as a regular jar. Functionality everything looks ok.<br>
          ><br>
          > During the performance test we observed very high cpu
          usage when nashorn engine's 'eval' is called.  The CPU
          consumption is so high that instances are throttled and
          performance becomes 10x slower compared to java-11.<br>
          ><br>
          > Upon investigation using profiler (jvisualVM) looks like
          most of the CPU is spent in compile method, more specifically
          during ContextCodeInstaller.initialize and
          NamedContextCodeInstaller.install<br>
          ><br>
          > Looks like the compile method is optimized with cache,
          unfortunately the cache is in context scope, meaning it's not
          shared between ScriptEngines and Nashorn is not thread-safe
          (as per the docs) to use a single instance of ScriptEngine
          across all threads. Also the cache uses 'soft-reference',
          would it cause double whammy when there is a memory pressure.<br>
          ><br>
          > so, how to improve the performance of the Nashorn engine,
          specifically the `compile` part.<br>
          > Is there any other option we can try? BTW, 
          persistent-code-cache did not help as
          OptimisticTypesPersistence.getVersionDirName is performing
          poorly<br>
          ><br>
          > Test code that we used to study this high CPU issue is
          attached.<br>
          ><br>
          > Thanks a lot for hemp & any insight<br>
          > Sakkanan<br>
        </blockquote>
      </div>
    </blockquote>
    <pre cols="100"></pre>
  </div>

</blockquote></div>