|
The optimization was introduced in #2672 using (var cts = new CancellationTokenSource()) {
var engine = new Engine(o => o.CancellationToken(cts.Token));
engine.SetValue("sleep", (Action<int>)(ms => Thread.Sleep(ms)));
cts.CancelAfter(TimeSpan.FromMilliseconds(200));
var sw = Stopwatch.StartNew();
Action few = () => engine.Execute("for (let i = 0; i < 40; i++) { sleep(100); }"); // ~4s
few.Should().NotThrow("4.13.0 amortization skips the token check for a 40-iteration loop");
sw.Stop();
sw.ElapsedMilliseconds.Should().BeGreaterThan(3000, "so the loop runs to completion (~4s) despite the cancel");
} |
Replies: 2 comments
|
Thanks for the report — this was a real gap in the #2672 amortization, and it's fixed in #2713 plus the hardening follow-ups #2714/#2715 (will be in the next release). Rather than adding an option to disable or tune the amortization, the amortization itself was fixed. It bounded timeout/cancellation detection latency in statement count (64 statements), which is only a valid proxy for wall-clock time while statements stay cheap — and a statement that calls into host code can take arbitrarily long, exactly as in your repro. The engine now re-checks the time/cancellation constraints whenever control returns from host code to the interpreter (delegates registered via Your example now throws One caveat: if you host long-running CLR code behind a hand-built |
|
Thanks! |
Thanks for the report — this was a real gap in the #2672 amortization, and it's fixed in #2713 plus the hardening follow-ups #2714/#2715 (will be in the next release).
Rather than adding an option to disable or tune the amortization, the amortization itself was fixed. It bounded timeout/cancellation detection latency in statement count (64 statements), which is only a valid proxy for wall-clock time while statements stay cheap — and a statement that calls into host code can take arbitrarily long, exactly as in your repro. The engine now re-checks the time/cancellation constraints whenever control returns from host code to the interpreter (delegates registered via
SetValue, wrapped methods…