Search code examples
graalvm

nashorn CompiledScript graalvm equivalent


I have a fairly big file that needs to often be evaluated,

with nashorn I used to do something like that :

CompiledScript compiledScript = ((Compilable) engine).compile(text);

and later on, I could call many times the following :

Context context = new SimpleScriptContext();
compiledScript.eval(context);

this was quite fast.

Using the new Polyglot API, I do :

Source source = Source.newBuilder("js", myFile).build();

then :

Context context = Context.newBuilder("js").option("js.nashorn-compat", "true").build();
context.eval(source)

Using jmh, I have a big performance difference between the two

Benchmark                     Mode  Cnt   Score    Error  Units
JmhBenchmark.testEvalGraal    avgt    5  42,855 ± 11,118  ms/op
JmhBenchmark.testEvalNashorn  avgt    5   2,739 ±  1,101  ms/op

If I do the eval on the same context, it is working properly, but I don't want to have a shared context between two consecutive eval (unless the concept of Context of Graal is not the same as the one from Nashorn).


Solution

  • To reproduce your ScriptEngine setup with GraalVM, you should re-use the same Engine (org.graalvm.polyglot.Engine) and .close() the context after use:

    Source source = Source.newBuilder("js", myFile).build();
    Engine engine = Engine.create();
    

    and later:

    Context context = Context.newBuilder("js")
                             .engine(engine)
                             .option("js.nashorn-compat", "true").build();
    context.eval(source);
    context.close();
    

    Quoting the Context.Builder.engine documentation:

    Explicitly sets the underlying engine to use. By default, every context has its own isolated engine. If multiple contexts are created from one engine, then they may share/cache certain system resources like ASTs or optimized code by specifying a single underlying engine.