Hello sgammans!
Your first technique above (the one that goes through
Your second code sample executes the same
Frankly we're surprised that the second technique is faster. Our suspicion is that this is because (a)
By the way, in your second code sample, the line
But again, the other way is much better. It's simpler and cleaner, and it should be faster and more efficient in real-world situations.
If you're wondering then what the point of compilation is, consider a scenario where your client provides arbitrary script code (not a single script function) that you must execute many times. In this situation, the following:
is much faster than this:
In addition, compiled scripts can be shared among multiple
Cheers!
Your first technique above (the one that goes through
ScriptEngine.Script
) is the right way to invoke an existing script function multiple times. We'd actually recommend caching a reference to the function:V8ScriptEngine engine = new V8ScriptEngine(); engine.Execute(code); dynamic computeFoo = engine.Script.computeFoo; for (int i = 0; i < 50000; i++) { var result = computeFoo(getFoo(i)); // do something here with result }
function
statement over and over, needlessly redeclaring the function 50000 times. In addition to making it difficult to pass arguments, this could create 50000 copies of the function for the garbage collector to clean up. We say could because V8 might be smart enough to optimize the duplicate functions away.Frankly we're surprised that the second technique is faster. Our suspicion is that this is because (a)
computeFoo()
is trivial, and (b) V8 is very good at avoiding duplicate work.By the way, in your second code sample, the line
foo = getFoo(i);
only reassigns the .NET variable foo
; it does not affect the script variable hostFoo
. If we're reading your code correctly, this means that computeFoo()
will operate on the same Foo
instance every time. The code should probably be something like this instead:V8ScriptEngine engine = new V8ScriptEngine(); // Foo foo = new Foo();// engine.AddHostObject("hostFoo", foo); V8Script compiledCode = engine.Compile(code); for (int i = 0; i < 50000; i++) { // foo = getFoo(i); engine.Script.hostFoo = getFoo(i); var result = engine.Evaluate(compiledCode); // do something here with result }
If you're wondering then what the point of compilation is, consider a scenario where your client provides arbitrary script code (not a single script function) that you must execute many times. In this situation, the following:
void ExecuteManyTimes(V8ScriptEngine engine, string code, int repeatCount) { using (var compiledCode = engine.Compile(code)) { for (var i = 0; i < repeatCount; i++) { engine.Evaluate(compiledCode); } } }
void ExecuteManyTimes(V8ScriptEngine engine, string code, int repeatCount) { for (var i = 0; i < repeatCount; i++) { engine.Evaluate(code); } }
V8ScriptEngine
instances that share a single V8Runtime
.Cheers!