Subj : Re: SpiderMonkey and threads To : netscape.public.mozilla.jseng From : Brendan Eich Date : Tue Mar 29 2005 11:57 am Mads Bondo Dydensborg wrote: > My use case is a program running several hundreds instances of the same > script - think php like, serving 100s of pages at the same time that is > the output of a spidermonkey script. Each request will be managed by its > own thread. > > Now, all scripts are the same. What is the most ressource efficient way > to organize this? > > Should the SpiderMonkey engine be compiled with thread support, or > should I organize for each thread to run its own engine? The former -- you want JS_THREADSAFE defined, and probably a single JSRuntime (people sometimes use multiple to force GC independently per request, but I believe that's suboptimal in time and space). > I am a bit worried about the overhead in setting up a runtime, context, > and compile the script for each request. (I guess I can pool a number of > runtimes, and have my threads acquire them from there, and placing them > back when they are done). You want *1* runtime per process, not per thread. The runtime contains the GC heap, so all objects that might be shared among threads. If you share no objects among threads, you could stand to have separate runtimes but (as noted above) this generally just wastes space, and time dealing with the wasted space. You need one context per thread concurrently executing JS. So if you have a pool of N threads, you could assign M < N contexts to the M threads that concurrently want to execute. Associating threads and contexts in a pool is pretty easy; see JS_{Get,Set}ContextPrivate. > Is there a way to share scripts across contexts, or runtimes? It would > seem that having 100 instances of essentially the same script is a bit > redundant in memory use. Of course, and there's no reason to do that -- why would there be? A script is immutable once compiled, and can be shared with any number of threads. A context is per-thread, and cannot be used by more than one thread at a time. This should be clear when you consider that the context contains the interpreter stack and virtual machine "registers". > Can I share scripts by creating a script object, and pass this to > JS_ExecuteScript? (Objects are shared across contexst, I believe). Objects are in the runtime's GC heap, they have no particular affinity for contexts. Contexts are for execution, they are not where objects are stored. > If I set the global object using JS_SetGlobalObject, and execute a > script associated with this, can this global object be reused across > several contexts? (I believe this is the meaning of the figure 1.3 in > the guide, yes?) You could, but you wouldn't want to do that concurrently -- the racing scripts would clobber one anothers' global variables. But if you pool contexts to active JS-executing threads as sketched above, you can of course reuse a global object serially. You'll want to JS_ClearScope before reuse, and probably want to use lazy standard class init (see js.c, look for LAZY_STANDARD_CLASSES). > What is the impact of using 100 of threads on a single runtime, if all > threads wants to e.g. call the Date Object? Each thread if executing concurrently with the 99 others should have its own global object, which will have its own Date constructor/function if it uses it (per the lazy standard class init suggestion above). The underlying native C code for Date is threadsafe. > Sorry for my wild "shotgun" questions - google unfortunately does not > turn up a lot, other than "SpiderMonkey supports multithreaded > execution". Which is nice to know, but not really very helpful ;-) You shouldn't expect to have to clone a script to run it in another thread -- that would be insane, and if SpiderMonkey required it, you should run screaming to another JS engine. > I did read the docs for JS_SetContextThread, JS_GetContextThread and > JS_ClearContextThread, but did not learn anything substantial. You shouldn't need those unless you actually pool contexts to threads. Then, when reassigning a free context to a thread that has no context associated, but that wants to begin calling the JS API, you'd want to JS_SetContextThread. When putting the context into the pool's LRU freelist, JS_ClearContextThread. More important APIs to learn and use are JS_BeginRequest, JS_EndRequest, etc. I fixed the API docs on those last year some time, so they are in reasonable shape. /be .