JDK-8041697 : CompiledScript slower when eval with binding
  • Type: Bug
  • Component: core-libs
  • Sub-Component: javax.script
  • Affected Version: 8u40
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2014-04-24
  • Updated: 2016-06-13
  • Resolved: 2014-05-07
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
8u20Fixed 9 b13Fixed


I found if the script is evaled with binding, the execution time increased
a lot.
Do you know the reason?
Check this

String script_text = "var a = 1";

       ScriptEngineManager manager = new ScriptEngineManager();
       ScriptEngine engine = manager.getEngineByName("js");
       CompiledScript script = ((Compilable) engine).compile(script_text);

       Bindings bindings = engine.createBindings();

       long dt = new Date().getTime();
       for (int i = 0; i < 100000; i++) {
           //script.eval(bindings); // switch to this line and feel the
slow speed,
       System.out.println(new Date().getTime() - dt);

Best wishes
NashornScriptEngine's CompiledScript compiles and evals again if different ENGINE_SCOPE Bindings is used. While Nashorn compiler will still find compiled class for that source from cache again, there is still a lot of overhead such as 1) check Source and CACHE 2) look for "run script" methods + handle script 3) create ScriptFunction object for "run script" method Except for step (3), we can avoid first 2 steps by caching MethodHandle and strict mode flag of compiled code in a "reusable compiled script object". We just need to construct ScriptFunction for that method handle + strict mode flag within the new global scope object. I made changes to nashorn Context and NashornScriptEngine classes to do different caching for CompiledScript. With that, I get 470 for compiledScript.eval(ScriptContext) - which is about 2x of compiledScript.eval() -- much better than previous score of 1797.

javax.script.CompiledScript has three eval methods: 1) eval() 2) eval(Bindings) 3) eval(ScriptContext) The Bindings accepting method creates a fresh ScriptContext - prepares it by making new Bindings as it's ENGINE_SCOPE bindings, copies engine default context's writer, reader etc. After preparing new context, it calls CompliedScript.eval(ScriptContext) variant! The eval(Bindings) is called inside the loop in the test provided. Instead if we create ScriptContext outside the loop and call compiledScript.eval(ScriptContext) in the loop, we get much better numbers. I used jdk8 GA on Ubuntu java version "1.8.0" Java(TM) SE Runtime Environment (build 1.8.0-b132) Java HotSpot(TM) Server VM (build 25.0-b70, mixed mode) File attachment: Main1.java - same as provided test except for imports, main etc. added. javac Main1.java java Main1 5741 File attachment Main2.java : ScriptContext outside loop: javac Main2.java javac Main2 1797 Yes, it is still slow compared to compileScript.eval() which gives me 234 but creating/passing ScriptContext outside loop improves the situation a lot.

Two tests Main1, Main2 attached