Skip to content

rust test: Parallelize Slint compiler execution (and fix a stack usage hotspot) - #12691

Merged
ogoffart merged 2 commits into
masterfrom
olivier/ci
Jul 29, 2026
Merged

rust test: Parallelize Slint compiler execution (and fix a stack usage hotspot)#12691
ogoffart merged 2 commits into
masterfrom
olivier/ci

Conversation

@ogoffart

Copy link
Copy Markdown
Member

The test-driver-rust build script compiled every test case sequentially (twice each, due to the deterministic-output check). It was the longest single unit of the integration test build in CI: 287 seconds on the 4-core Windows runner, during which the dependent test binaries can't start compiling.
This PR distributes the cases over all cores with rayon.
The script drops from 160 s to 13 s on my 24-core machine
(expect ~2.5–3× on CI runners).

Moving the 512 KB small-stack guard from a per-case thread onto the rayon pool exposed that the guard had almost no headroom left. The second commit splits the pass's heavy match arms into separate functions.

ogoffart added 2 commits July 29, 2026 12:46
…ript

The build script processed the test cases sequentially. With the
build-time feature each case runs the Slint compiler, twice with
deterministic-output, which made the script the longest single unit of
the integration test build in CI: 287 seconds on the 4-core Windows
runner, during which the dependent test binaries cannot start compiling.

Distribute the cases over all cores with rayon. par_iter preserves the
input order, so the module declarations in the generated files don't
depend on thread scheduling. compile_syntax_node is thread safe.

The 512KB stack size that compile_and_generate applied with a dedicated
thread per compiler call is set on the pool workers instead. A dedicated
pool with install() is used rather than the global pool, because with
the global pool the calling thread also executes jobs on its own large
stack, which would exempt some cases from the small-stack check.

The generated output is byte-identical to the sequential version for
the full test corpus (822 files). On a 24-core machine the script goes
from 160 to 13 seconds.
process_expression recursed with an 18KB stack frame in debug builds:
the function held the temporaries of every match arm, and debug builds
give each temporary its own stack slot. A 25-deep else-if chain was
enough to overflow the 512KB stack that the rust test driver uses as a
canary for environments with small stacks.

Move the heavy arms (Condition, StoreLocalVariable) into their own
functions, and split the merging of the processed branches out of
process_condition so that its temporaries don't occupy the frame
during the recursive calls. A recursion level now needs 4.6KB instead
of 18.6KB.

The generated code is unchanged; the worst case over the whole rust
test corpus now compiles with a 416KB stack instead of 480KB, and the
new limiting factor is the resolving pass on long chains of binary
operators.
@ogoffart
ogoffart merged commit c06f140 into master Jul 29, 2026
95 of 97 checks passed
@ogoffart
ogoffart deleted the olivier/ci branch July 29, 2026 14:24
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.

2 participants