Isolated contexts and multithreading

Sep 20, 2014 at 5:55 AM
Edited Sep 20, 2014 at 5:56 AM
Hi, another question. In the V8 embedders guide it talks about using different contexts in order to isolate execution environments from each other. I have an application that has a whole tonne of admin-defined rules and scripts that need to run in isolation from different threads without affecting each other. Sometimes there will be in excess of 50 different threads running their own script calculations in isolation from each other in very close time proximities. Now, I saw that there is a thing called "isolates" that it looks like you've handled internally? This allows calls to remain thread safe, but I'm not sure if V8DotNet provides any way to isolate execution using contexts, seeing as the global object is itself a context, and it appears to be a first class property of the engine object. However if I try to create a large bool of engine objects, ready to run, each preloaded with a few javascript libraries I need to use, around the 40-50 engine instance mark my application crashes with the error:

# Fatal error in heap setup
# Allocation failed - process out of memory

... edit: I just realised that because a single execution call is blocking, and my scripts need to make blocking calls back into my .net code, and some of those calls may take anywhere from 10-30 seconds to complete, as they are resolving external data, I can't use a single engine instance with different contexts, as each call to Execute() would be blocked by any other unresolved Execute() calls.

Going to have to rethink things a bit I think. Any input is welcome...
Coordinator
Sep 20, 2014 at 10:01 PM
Edited Sep 20, 2014 at 10:03 PM
You are correct - for multiple threads you would need a dedicated isolate and context (basically a new engine instance - the nature of Google's V8 engine). I haven't thoroughly tested opening a large number of engines, so there may be issues I haven't found yet.
Sep 21, 2014 at 8:25 AM
I am using 10 instances, so not as much as you would like to have :-)

While I want to run only one JavaScript at a time, setting up an Engine may take some seconds (not many, but an ugly delay anyway). This is why I create them in advance and put them in a Queue, where they wait until they are needed. That works like a charm.

I use an AsyncOperation to make sure that Engine.LoadScript is called on the same thread that the engine was created, as I ran into problems otherwise. If you create and execute a script in the same Thread but isolated from each other, you should be fine, thus.

Please tell us your findings :-)
Coordinator
Sep 21, 2014 at 9:58 PM
A native V8 locker is used, so multiple thread access should work (my V8.net worker thread calls into it ok). I haven't tried multiple threads to run scripts, so I'll have to see what's up...
Sep 22, 2014 at 12:05 PM
As Phil said, the initialization time was an important factor for me too. Unfortunately the crashing after 45-50 engine instances was a showstopper for me, so for now I've switched to pure C# scripting. I'll definitely come back to V8.Net next time I have a scripting need though!
Coordinator
Sep 23, 2014 at 3:43 AM
Side note: V8.Net is geared to be used in a JavaScript server I'm creating (think a .NET version of NodeJS), so this will become an optimized focal point soon down the road when I'm ready for that part. ;)