Skip to content

interp: bail out of loops that iterate too many times#5395

Open
jakebailey wants to merge 2 commits into
tinygo-org:devfrom
jakebailey:fix-2090
Open

interp: bail out of loops that iterate too many times#5395
jakebailey wants to merge 2 commits into
tinygo-org:devfrom
jakebailey:fix-2090

Conversation

@jakebailey
Copy link
Copy Markdown
Member

Fixes #2090

This adds a loop limiter to interp so it can still bail out even if nothing else does. Perhaps this is a bad idea (1000 is random), but it does seem to fix the problem?

entries before after
5,000 7.4s 2.1s
10,000 17.5s 2.1s
20,000 48.0s 2.8s
65,536 >180s (OOM) 3.2s

The existing loop guard (errLoopUnrolled) only fires when a loop body
emits runtime instructions. Loops that are fully evaluable at compile
time, such as inserting thousands of entries into a map, were not
caught and could hang the compiler.

Add a per-basic-block iteration counter that triggers a recoverable
error (errLoopTooLong) when any block is entered more than 1000 times
in a single function call. This defers the init function to runtime,
which is the same behavior as other interp bailouts.

Profiling showed that 83% of CPU time was spent in GC, caused by
allocation pressure from the interp memory cloning on each map
mutation. The iteration limit avoids this entirely by bailing out
before the quadratic cost becomes significant.

Performance on the reproducer from tinygo-org#2090 (map init with strconv.Itoa):

    entries  before       after
    5,000    7.4s         2.1s
    10,000   17.5s        2.1s
    20,000   48.0s        2.8s
    65,536   >180s (OOM)  3.2s
@dgryski
Copy link
Copy Markdown
Member

dgryski commented May 11, 2026

See also #2384

@jakebailey
Copy link
Copy Markdown
Member Author

Yeah, I definitely read that one but of course agree that a time-based solution is a no-go.

@dgryski
Copy link
Copy Markdown
Member

dgryski commented May 12, 2026

Can you add a flag to make this value configurable? (With 0 == disable?). There might be some users who want the slowness in exchange for fully interpreting a loop they know to be huge. Would need to figure out how to make it play nicely with the current time-based timeout.

@jakebailey
Copy link
Copy Markdown
Member Author

Done; please bikeshed the flag name 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

interp timeout compiling large maps with runtime inits

2 participants