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