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