Reusing compiled JS code keeping speed and thread-safety

Tal Liron tal.liron at threecrickets.com
Thu Oct 30 14:33:10 UTC 2014


As Hannes stated, you can use the lower-level CompiledScript directly, 
and avoid this "pollution", as you call it.

The problem with ScriptEngine (JSR-223) is that it simply doesn't 
specify threading behavior, so you can't fault the Nashorn team for not 
adhering to a non-existent spec. If you look around at JSR-223 
implementations of other language engines, you'll find a variety of 
(incompatible) approaches to the problem of threading. I think JSR-223 
is simply not a good solution for concurrent applications (unless the 
implementation for a particular engine does the "right thing" in terms 
of your expectations).

Sorry for self-advertising, but I do think it's relevant: this is 
exactly the reason why I created Scripturian as an alternative to JSR-223:

http://threecrickets.com/scripturian/

The idea was to have a very strictly defined threading model for all 
engines, exactly so that you can embed them in high-concurrency 
applications. In some cases this proved impossible: Scala and Kotlin 
cannot be supported, it seems, do to their reliance on global 
singletons. But Nashorn, Rhino, Groovy, Quercus (PHP), Luaj, Jython, 
JRuby, Velocity and Succinct are.

Note, though, that for Nashorn you want to use a recent build from the 
Mercurial repository. Also note that since Nashorn does not, at this 
point, support caching of compiled code to disk, this Scripturian 
feature is not supported for Nashorn. The consequence is that Nashorn 
applications have a *very* slow start-up as compared to other engines, 
as it needs to compiled all the code, though once it is up and running 
performance is generally excellent.

On 10/30/2014 10:03 PM, Benjamin Sieffert wrote:
> Hello there,
>
> we had a similar aim / similar issues with nashorn. Since I don't know your
> code exactly, I'll just describe our case / what we ended up doing and
> maybe you can get some ideas off that.
>
> We use one ScriptEngine. Among all our threads, just one engine. On
> start-up we let it compile the library once. The library has no mutable
> state and is not dependant on global variables. It's just a collection of
> functions / classes.
> Then we have a few hundred small javascripts that basically instantiate a
> class defined by the library and do some configurations on that instance.
> Any one of these scripts gets evaluated by the engine once and the returned
> ScriptObjectMirror (the configured javascript object) is then kept on the
> java side. As this ScriptObjectMirror also does not have any mutable state,
> we can now safely use it among multiple threads via callMember().
> To get nice stack traces, we also wrap each small javascript into a
> load()-call in the engine and name it. The library is also wrapped in a
> load()-call.
>
> All approaches including some sort of mutable javascript-side state sadly
> do not seem to be workable. The nashorn devs have (understandably)
> explicitly stated that since javascript does not define multithreaded
> semantics, they will not be implementing any.
> Everything evaluated in a NashornScriptEngine keeps its original
> context/global, even when seemingly "put" into another engine. You cannot
> prevent pollution. I tried for some time. : )
>



More information about the nashorn-dev mailing list