We are currently in the process of adding a server-side scripting capability to one of our products. As part of this I am evaluating JSR 223 script engines. As we may potentially be running large numbers of scripts on the server, I am particularly concerned about memory usage of these script engines. Comparing Rhino (Apple JDK 1.6.0_65-b14-462-11M4609, Mac OS X 10.9.2) with Nashorn (Oracle JDK 1.8.0-b132) there seems to be a dramatic difference in memory usage per ScriptEngine instance.
To test this, I use a simple program that fires up 10 blank ScriptEngine instances and then blocks reading from stdin. I then use jmap to take a heap dump (jmap -dump:format=b,file=heap.bin ) and then search for the relevant script engine instance in the dump:
import javax.script.*;
public class test {
public static void main(String...args) throws Exception {
ScriptContext context = new SimpleScriptContext();
context.setWriter(null);
context.setErrorWriter(null);
context.setReader(null);
ScriptEngine js[] = new ScriptEngine[10];
for (int i = 0; i < 10; ++i) {
js[i] = new ScriptEngineManager().getEngineByName("javascript");
js[i].setContext(context);
System.out.println(js[i].getClass().toString());
}
System.in.read();
}
}
The reason for nulling out the various reader/writer fields in the context is because we do not use them, and earlier heap dumps for Rhino suggest that they constitute a significant fraction of the per-instance overhead (and do not appear to be shared).
Analysing these heap dumps in Eclipse MAT then I get the following per-instance retained heap sizes:
Is this 24x increase in size for Nashorn to be expected? Execution speed is not a major concern for the scripts we will be executing (which will mostly be I/O bound), so I am considering shipping our own copy of Rhino for use in Java 8+.
JAXenter: The motivation behind the proposal to deprecate Nashorn was that it is “challenging to maintain”.
The Nashorn engine has been deprecated in JDK 11 as part of JEP 335 and and has been removed from JDK15 as part of JEP 372.
Java SE 8 will instead ship with a new engine called Oracle Nashorn, which is based on JSR 292 and invokedynamic . It provides better compliance with the ECMA normalized JavaScript specification and better runtime performance through invokedynamic -bound call sites.
Nashorn: Nashorn is a JavaScript engine which is introduced in JDK 8. With the help of Nashorn, we can execute JavaScript code at Java Virtual Machine. Nashorn is introduced in JDK 8 to replace existing JavaScript engine i.e. Rhino.
What is Nashorn?
Nashorn is a JavaScript engine for the JVM that is released with Java 8. Nashorn comprises an embedded JavaScript interpreter and a command-line tool. The objective of Nashorn is to implement a high-performance JavaScript runtime in Java with a native JVM. Using Nashorn, a developer can embed JavaScript in a Java application and can also invoke Java methods and classes from the JavaScript code providing seamless integration between the two languages.
Why high memory consumption?
Nashorn objects and property maps do not currently scale to lots of properties. The reason for making PropertyMap immutable is to allow quick validation of inline call sites by comparing PropertyMap references. This will lead to high memory consumption in Nashorn.
One solution would be to switch to pre-script-java-functions, because in java server it will have the java functions for a particular task and from Nashorn engine, you will call that function it won't create object mapping and everything it will only execute the function in java and give you the result so memory consumption is comparatively low rather than using JS functions map everything in Java. These kinds of pre-script-java-functionsare used in WSO2-Identity Server Adaptive Script functionality. This is one way of handling high memory allocation and memory consumption in Nashorn.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With