Greetings!
Thank you for the positive feedback!
Easy access to script objects and functions is one of ClearScript's fundamental goals. That said, accessing a script object or invoking a script function is relatively expensive. It involves the use of .NET's dynamic infrastructure, managed-to-native transitions, argument marshaling, lock acquisition, etc.
It really depends on your application's requirements. If you need concurrent script execution, you need multiple engines. If you need to run each script in a pristine environment, you can use one V8 runtime to efficiently spawn a separate engine for each script, or just create and dispose engines as necessary. There are definitely tradeoffs, but even for server applications that require maximum concurrency, we recommend using a small pool of engines or runtimes. As with worker threads, the sweet spot is somewhere in the neighborhood of your CPU core count.
The CLR and the script engine have independent object systems and garbage collectors, and proxies are used on each side to refer to objects on the other. A proxy by necessity prevents its target from being collected. When the proxy itself is collected, its target is released to its garbage collector only if no other reachable references exist on either side.
In your case, the script leaves global references to
Another consideration is that V8's garbage collector is extremely lazy. If your application uses long-lived
Thanks again, and good luck!
Thank you for the positive feedback!
Is this a good idea? Should I be holding on to references to functions that exist in the script the way I am? Are there bad performance implications of doing so?
Easy access to script objects and functions is one of ClearScript's fundamental goals. That said, accessing a script object or invoking a script function is relatively expensive. It involves the use of .NET's dynamic infrastructure, managed-to-native transitions, argument marshaling, lock acquisition, etc.
Does it make sense to have one engine for all scripts? From what I've been reading it's expensive to create multiple engines. I may have 20-30 different scripts, so it sounds like I don't want 30 different engines running.
It really depends on your application's requirements. If you need concurrent script execution, you need multiple engines. If you need to run each script in a pristine environment, you can use one V8 runtime to efficiently spawn a separate engine for each script, or just create and dispose engines as necessary. There are definitely tradeoffs, but even for server applications that require maximum concurrency, we recommend using a small pool of engines or runtimes. As with worker threads, the sweet spot is somewhere in the neighborhood of your CPU core count.
I'd love to listen for file changes and automatically update the running engine using the method above. I can do book keeping and get rid of my C# references to the js functions for that file. However the engine would still hold those references wouldn't it? Would the engine know to clean those up?
The CLR and the script engine have independent object systems and garbage collectors, and proxies are used on each side to refer to objects on the other. A proxy by necessity prevents its target from being collected. When the proxy itself is collected, its target is released to its garbage collector only if no other reachable references exist on either side.
In your case, the script leaves global references to
myFunction1()
and myFunction2()
, so they can't be collected even after the managed references are gone. It would be different if your script looked like this:components.init = function (container) { container.register('typeOfData1', function (args) { /* do stuff */ }); container.register('typeOfData2', function (args) { /* do stuff */ }); }
V8ScriptEngine
or V8Runtime
instances, we strongly recommend that you periodically call CollectGarbage()
.Thanks again, and good luck!