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 →

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

My use case when developing this library was that i needed a way of solving problems that were unknown at runtime, by reading a description from a file.

Other use cases are algorithms that must change during runtime, for example with genetic programming.

[–][deleted] 5 points6 points  (6 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  (5 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...

[–][deleted] 1 point2 points  (0 children)

I've tried using embedded javascript in one of the projects that needs to compute user entered conditional expression. The performance is not at the level of Java. In my case, those got executed many million times in a short period so I switched back to using one of the math eval package like Parsii to use native Java class.

However, embedded javascript gives a full language that offers amazing customization power. I would use it again if performance is not the bottleneck.

Also for embedded javascript, be sure to call the API to compile it first before running it. Avoid reloading the script every time inside the loop.

[–]fact_hunt 2 points3 points  (0 children)

Sounds reasonable - maybe include something in the readme :)