Skip to content

ci(test): serialize only GPU readbacks, run tests in parallel again - #236

Merged
DWAA1660 merged 3 commits into
AlienTechSoftware:mainfrom
DWAA1660:ci/serial-gpu-tests
Nov 14, 2026
Merged

DWAA1660 merged 3 commits into
AlienTechSoftware:mainfrom
DWAA1660:ci/serial-gpu-tests

Conversation

@DWAA1660

Copy link
Copy Markdown
Collaborator

What and why

Since #221, .cargo/config.toml sets RUST_TEST_THREADS = "1" for the whole workspace, because the UI tests' pixel readbacks from the shared offscreen GPU device came back blank when run in parallel. That made every test in every crate run one at a time. The CI test step went from about 5 minutes to about 15 on Linux, Windows and macOS, and coverage went from about 6 to about 16. Every run before 82474fa showed the first numbers and every run from #221 on shows the second (job timings from the Actions API).

Only the readback has to wait its turn, so that's all this locks:

  • crates/ui-egui/tests/support/gpu.rs gets render(h), which holds a process-wide lock around Harness::render. All 17 picture readbacks in ui.rs (including review) go through it. Building windows, stepping, clicking and typing still run on every test thread, and that's most of the suite's time.
  • icons_visual.rs shares its own device the same way, so its one readback takes the same kind of lock.
  • The global RUST_TEST_THREADS is removed, so every other test binary runs in parallel again.
  • website-pipeline.yml restores Swatinem/rust-cache (same pinned SHA as ci.yml). It only saves from main, which the nightly release builds every night, so PR builds of the WASM demo stop compiling every dependency from scratch.

Quality level L3 (see SKILLS/nc-devx/SKILL.md)

  • The branch is rebased on main and has no merge commits
  • cargo xtask ci passes
  • Coverage: the coverage job's warnings are read; cargo xtask coverage --update is in this pull request if coverage rose (test-only change, no product code touched)
  • Docs match the change (nothing in docs describes the serial test threads)
  • A new user action is a CommandSpec with a test (not applicable)
  • Page or demo changes (not applicable)
  • UI changes (not applicable: no product UI changed)
  • New files under assets/ or docs/images/ (not applicable)

How it was checked

On Linux (Ubuntu 24.04, mesa lavapipe, same packages as CI):

ui.rs run (255 tests) Time Result
Serial (RUST_TEST_THREADS=1, as on main) > 590 s (stopped) n/a
4 threads, no lock 215 s 255 passed
8 threads, no lock 121 s 255 passed
4 threads, with this lock 213 s 255 passed
Default threads via cargo test (ui + icons_visual), with this lock 401 s + 5 s on 2 cores all passed

The lock costs nothing measurable. cargo xtask ci (fmt, clippy, test, i18n-audit, layers, assets, docs, text, demo-check) passed end to end on this branch.

Not checked: I couldn't reproduce the blank readbacks from #221 on lavapipe even without the lock, so I couldn't confirm the lock on the hardware GPU where they happened. If they come back there, the next step would be to also hold the lock while windows are stepped (texture uploads), still per test rather than per workspace. This PR's CI runs on Windows and macOS will show it on those runners.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Y4im4p9XKJUrt6XFpFMUox

DWAA1660 and others added 3 commits November 13, 2026 17:44
`.cargo/config.toml` set RUST_TEST_THREADS=1 for every test in the workspace
because UI tests reading pixels back from the shared offscreen GPU device came
back blank when run in parallel. That tripled the CI test step on every
platform and in coverage (about 5 to 15 minutes since AlienTechSoftware#221).

Only the readback needs to wait its turn: ui.rs now takes pictures through
support::gpu::render, which holds a lock around Harness::render, and
icons_visual.rs does the same around its single readback on its own shared
device. Building windows, clicking and typing run on every test thread again.

The website pipeline also restores the Rust dependency cache (saved only from
main, which the nightly release builds), as ci.yml already does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y4im4p9XKJUrt6XFpFMUox
@DWAA1660
DWAA1660 merged commit 88ca603 into AlienTechSoftware:main Nov 14, 2026
10 checks passed
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.

1 participant