ClearScript
ClearScript copied to clipboard
Need best practices guides for performance and memory usage
I can't stress this enough. I'm trying to integrate this into my project, and I'd like to safely add usage and resource limits. What areas I'm struggling with:
- How the V8RuntimeConstraints worked, and some sample documentation on how to properly set reasonable size limits for user run code.
- How do I limit execution time? With jint, I can specify a cancellation token to cancel the currently running script.
- How to kill processes that hog the CPU:
engine.Execute(@"
while (true) {}
");
- How the engine works with asynchronous code:
public class TestApi
{
private delegate void Executor(dynamic resolve, dynamic reject);
private static async Task<string> Delay(string msg)
{
await Task.Delay(2000);
return msg;
}
public static object delay(string msg)
{
var task = Delay(msg);
var ctor = (ScriptObject)ScriptEngine.Current.Script.Promise;
return ctor.Invoke(true, new Executor((resolve, reject) => {
task.ContinueWith(t => {
if (t.IsCompleted)
{
resolve(t.Result);
}
else
{
reject(t.Exception);
}
});
}));
}
}
engine.AddHostType("Console", typeof(Console));
engine.AddHostType("api", typeof(TestApi));
engine.Execute(@"
Console.WriteLine('start');
const main = async () => {
Console.WriteLine('main');
var res = await api.delay('end');
Console.WriteLine(res);
}
main();
");
If I wrap this in a using block, it will output:
start
main
and then dispose of the engine
If I execute this, and add a Console.ReadKey(); before the engine gets disposed, after 2 seconds it correctly outputs end. There's no documentation on how to wait until execution of all callbacks is completed.
Hi @danbopes,
- How the V8RuntimeConstraints worked, and some sample documentation on how to properly set reasonable size limits for user run code.
We generally recommend that applications stay away from V8RuntimeConstraints.
Originally this API was somewhat suitable for sandboxing, but the V8 team decided years ago that constrained script execution isn't a goal for V8. Today, exceeding any of the specified limits causes V8 to crash instantly, and that's by design.
The API might still be useful for expanding V8's default limits, but we've found that V8 can then hit other limits that are inaccessible and vary unpredictably from version to version.
ClearScript does offer support for "soft limits" (see MaxRuntimeHeapSize, MaxRuntimeStackUsage), but as they require external monitoring via periodic timers, we can't guarantee their effectiveness in all cases.
The bottom line is that, unfortunately, if you must run untrusted script code with 100% safety, you'll need a Chromium-like multi-process architecture. The V8 team equates executing untrusted script code with invoking a function in an untrusted DLL.
V8's API is constantly changing though, and we'll continue to watch for new developments.
- How do I limit execution time? With jint, I can specify a cancellation token to cancel the currently running script.
- How to kill processes that hog the CPU
For these purposes you can use ScriptEngine.Interrupt.
There's no documentation on how to wait until execution of all callbacks is completed.
There's no special API for that, but you can always wait for a pre-arranged completion signal:
engine.AddHostType("Console", typeof(Console));
engine.AddHostType("api", typeof(TestApi));
engine.Script.done = new ManualResetEventSlim();
engine.Execute(@"
Console.WriteLine('start');
const main = async () => {
Console.WriteLine('main');
var res = await api.delay('end');
Console.WriteLine(res);
done.Set();
}
main();
");
engine.Script.done.Wait();
Please send any additional questions or comments our way.
Thanks!