Hello sgammans!
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
}
Your second code sample executes the same
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
}
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:
void ExecuteManyTimes(V8ScriptEngine engine, string code, int repeatCount)
{
using (var compiledCode = engine.Compile(code))
{
for (var i = 0; i < repeatCount; i++)
{
engine.Evaluate(compiledCode);
}
}
}
is much faster than this:
void ExecuteManyTimes(V8ScriptEngine engine, string code, int repeatCount)
{
for (var i = 0; i < repeatCount; i++)
{
engine.Evaluate(code);
}
}
In addition, compiled scripts can be shared among multiple
V8ScriptEngine
instances that share a single
V8Runtime
.
Cheers!