Thanks Rony & Ben, Using JavaFX is an interesting idea, but that is a huge change for us and not the first choice at this point in time.
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 ) . Converting Context.ClassCache <https://github.com/openjdk/nashorn/blob/main/src/org.openjdk.nashorn/share/classes/org/openjdk/nashorn/internal/runtime/Context.java#L387> 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 Do you see any issue in making Context.ClassCache <https://github.com/openjdk/nashorn/blob/main/src/org.openjdk.nashorn/share/classes/org/openjdk/nashorn/internal/runtime/Context.java#L387> as global cache. Really appreciate your help. thanks Sakkanan Here is the decompile 'script' class for reference ============================== package org.openjdk.nashorn.internal.scripts; import org.openjdk.nashorn.internal.runtime.PropertyMap; import org.openjdk.nashorn.internal.runtime.ScriptFunction; import org.openjdk.nashorn.internal.runtime.ScriptObject; import org.openjdk.nashorn.internal.runtime.ScriptRuntime; import org.openjdk.nashorn.internal.runtime.Source; public class Script$1$\^eval\_ extends JS { private static Source source; private static Object[] constants; public static final boolean strictMode = false; public static boolean :program(ScriptFunction :callee, Object :this) { ScriptObject :scope = :callee.getScope(); JO0P0 jO0P0 = new JO0P0(:getMap(0), :scope); :scope = ScriptRuntime.mergeScope((ScriptObject)jO0P0); return false; } public static ScriptFunction :createProgramFunction(ScriptObject paramScriptObject) { return ScriptFunction.create(constants, 1, paramScriptObject); } public static PropertyMap :getMap(int paramInt) { return (PropertyMap)constants[paramInt]; } public static void :setMap(int paramInt, PropertyMap paramPropertyMap) { constants[paramInt] = paramPropertyMap; } } =========== On Sat, Oct 26, 2024 at 7:50 AM Rony G. Flatscher <[email protected]> wrote: > 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? > > 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). > > 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 openjdk.org) first? > > ---rony > > > On 26.10.2024 00:45, Packiaraj S wrote: > > Thanks Ben. > I used visualVM just to compare CPU consumption between Java-11 & Java 21. > 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. > > On Fri, Oct 25, 2024 at 2:50 PM Ben Evans <[email protected]> > wrote: > >> You might try investigating further with a combination of JFR (JDK >> Flight Recorder, built-in to the JDK) and the GUI tool JMC (JDK >> Mission Control, available here: https://adoptium.net/en-GB/jmc/) >> >> I often find it to be significantly more useful than the capabilities >> of VisualVM. >> >> Thanks, >> >> Ben >> >> On Fri, Oct 25, 2024 at 4:21 PM Packiaraj S <[email protected]> >> wrote: >> > >> > Hello, >> > >> > 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). >> > 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. >> > >> > 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. >> > >> > Upon investigation using profiler (jvisualVM) looks like most of the >> CPU is spent in compile method, more specifically during >> ContextCodeInstaller.initialize and NamedContextCodeInstaller.install >> > >> > 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. >> > >> > so, how to improve the performance of the Nashorn engine, specifically >> the `compile` part. >> > Is there any other option we can try? BTW, persistent-code-cache did >> not help as OptimisticTypesPersistence.getVersionDirName is performing >> poorly >> > >> > Test code that we used to study this high CPU issue is attached. >> > >> > Thanks a lot for hemp & any insight >> > Sakkanan >> >
