Thanks Attila. This is the side-effect of Unsafe.defineAnonymousClass removal changes.
Just a thought. If script Engine can be shared across threads, would it be possible to make the script ClassCache global, like making classCache <https://github.com/openjdk/nashorn/blob/main/src/org.openjdk.nashorn/share/classes/org/openjdk/nashorn/internal/runtime/Context.java#L387> as static. That way cache is reused across threads and performance is also improved. I tried this solution and it seems to be working fine, but unfortunately due to Licensing (GPL v2) I am unable to make source code changes. On Fri, Nov 1, 2024 at 10:48 AM Attila Szegedi <[email protected]> wrote: > Hi Packiaraj, > > I suspect a particular issue might be at play here. Specifically, Nashorn > used to be able to rely on Unsafe.defineAnonymousClass to use a more > lightweight method to load compiled code. This was unfortunately taken away > with Java 17. You can test this assumption by running your system on Java > 16 and see whether the performance gets restored. Unfortunately, there's > not much we can do to fix that. Nashorn will use > Unsafe.defineAnonymousClass when available, but on Java 17+ it is no longer. > > However, you can, in fact, share ScriptEngine instances across threads, > and you should prepare all your scripts into CompiledScript instances if > you can. What you shouldn't share is Bindings. I wrote about this in some > detail in this SO answer: https://stackoverflow.com/a/30159424/131552, > and also less comprehensively here: > https://stackoverflow.com/a/34122641/131552 > > Hope this helps. > Attila. > > > On Fri, Oct 25, 2024 at 5: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 >> <https://github.com/openjdk/nashorn/blob/main/src/org.openjdk.nashorn/share/classes/org/openjdk/nashorn/internal/runtime/Context.java#L1454>, >> more specifically during ContextCodeInstaller.initialize >> <https://github.com/openjdk/nashorn/blob/main/src/org.openjdk.nashorn/share/classes/org/openjdk/nashorn/internal/runtime/Context.java#L217> >> and NamedContextCodeInstaller.install >> <https://github.com/openjdk/nashorn/blob/main/src/org.openjdk.nashorn/share/classes/org/openjdk/nashorn/internal/runtime/Context.java#L290> >> >> >> 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 >> >
