perf: compile-check reads assembly definitions and checks assemblies in parallel
Merged
HA
1d ago+308+308+012345678901234567890123456789-42-42-01234567890123456789
Summary
uloop compile-checkreads the project's.asmdeffiles, and checks each assembly's structure and sources, several at a time, so planning waits less on a large project.- Which assemblies it selects, which sources it compiles, and which error it reports when several things are wrong do not change.
User Impact
- Before: on a project with 561 assemblies, indexing the
.asmdeffiles took 35–58 ms and checking every assembly took about 112 ms, one file or assembly at a time. - After: up to eight reads or checks run at once, and the results are then read back in the same order as before. Measurements on a large project are pending.
Changes
- A helper that calls a computation for every index, up to eight at a time, and returns the results in index order once every call has finished.
- The
.asmdefindex reads every file's name and.metaGUID side by side first, then decides in root and walk order as before: the first of two files declaring the same name wins, and a root's read errors come before its walk error. The GUID of a losing duplicate and the files after an error are now read too, and never used. - Every assembly's structure check, source rebuild and change check run side by side. These only read the disk and the indexes built before them. The loop that records sources and reasons and returns the first error still walks the assemblies in name order, and within one assembly the checks keep their order, so the first error reported is the same. The checks of assemblies after a failing one now run too, and their results are dropped.
Verification
cli/dispatcher:golangci-lint fmt --diff,go vet ./...,golangci-lint run(0 issues), the complexity config (0 issues),go test ./..., andgo test -race ./internal/compilecheck/...pass. Coverage with the CI exclusions: 94.30% (baseline 94.2).cli/release-automation:go test ./...passes, including the architecture test on file length. The file-length check passes.- New tests: the helper puts each result at its index when the computations finish out of order, makes no call for zero, and never runs more than its limit at once; of two broken
.asmdeffiles in one root the first in walk order is reported (not the first by path); of two assemblies failing their own checks the first in name order is reported. Both order tests passed before the change. No existing test's expectations changed. - The reported error does not depend on the order the reads or checks finish in: two more tests hold the earlier file's read, or the earlier assembly's check, until the later one has returned its error, and expect the earlier error. Returning whichever error came back first fails them on every one of 50 runs.
- The functions run side by side were traced for writes to shared state: they only read the shared indexes and maps, and every slice they append to or sort is their own.
- Mutation checks, each restored afterwards, all fail a test: deciding the assemblies in reverse name order; reading each assembly's checks or each
.asmdefread from the neighbouring index; the helper running without its limit; and the helper placing results at the wrong index.