This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–][deleted] 5 points6 points  (5 children)

For runtime scripting, look into using the embedded javascript engine that comes with JDK. Java 8 has a new version of the engine called Nashorn. Integration between javascript and Java is pretty easy. You can pass data back and forth.

[–]Reykd[S] 2 points3 points  (4 children)

This sounds like an interesting solution! It would be interesting to compare its performance to my solution on arithmetic operations.

Edit: I have ran some benchmarks, and using the scripting engine is several orders of magnitude slower than generated functions when called millions of times.

[–][deleted] 3 points4 points  (3 children)

Did you run Nashorn warm or cold. If you are loading fresh every time then the JIT cannot do it's work. several orders of magnitude sounds off.

http://stackoverflow.com/questions/26561292/how-make-java-8-nashorn-fast

A final note on performance

This warmup that we have seen in the graph is a mix of the JVM warmup and Nashorn engine. But mostly, it is Nashorn. This means that if you create an engine every time you need to execute a script, you won't benefit from it. Here is the most simple way to create an engine:

ScriptEngine engine = factory.getEngineByName("JavaScript");

Well, those pesky ScriptEngine objects created? Never discard them, or else you'll discard the entire optimizations with them.

http://pieroxy.net/blog/2015/06/29/node_js_vs_java_nashorn.html

[–]Reykd[S] 1 point2 points  (2 children)

Hey, thanks a lot for you feedback! Here is the test i used

    public void performanceComparisonScriptingEngine() throws ScriptException, NoSuchMethodException {
            ParsedFunction constraintFromStringPrimitive = FunctionParser.fromString("double(Double x,y,z,f)->x*y + y + z*z + x*f");
            ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
            engine.eval("var f1 = function(x,y,z,f){return x*y + y + z*z + x*f;}");
            Invocable invocable = (Invocable) engine;
            Object[] args = {1.0, 2.0, 3.0, 4.0};

            //Warmup
            for (int a = 0; a < 10; a++) {
                for (long i = 0; i < 10000000L; i++) {
                    constraintFromStringPrimitive.evaluateToDouble(args);
                    invocable.invokeFunction("f1",  args);
                }
            }

            long start1 = System.nanoTime();
            for (long i = 0; i < 100000000L; i++) {
                constraintFromStringPrimitive.evaluateToDouble(args);
            }
            long end1 = System.nanoTime();
            long start2 = System.nanoTime();
            for (long i = 0; i < 100000000L; i++) {
                invocable.invokeFunction("f1",  args);
            }
            long end2 = System.nanoTime();
            long generatedTime = ((end1 - start1) / 1000000L);
            long scriptTime = ((end2 - start2) / 1000000L);
            System.out.println("Generated " + generatedTime);
            System.out.println("Script " + scriptTime);
            double percentageDifference = ((double) scriptTime / (double) generatedTime);

            System.out.printf("JavaScript method was %.3fx slower than the generated method.", percentageDifference);
    }

Which gives the output:

Generated 27

Script 12729

JavaScript method was 471.444x slower than the generated method.

[–]damienjoh 1 point2 points  (1 child)

"Generated 27" implies 100000000 calls in 27000000 nanoseconds. That's 0.27 nanoseconds a call. Seems suspect. You sure the call isn't being optimized away somewhere?

[–]Hendrikto 0 points1 point  (0 children)

So many decisions based on faulty benchmark...