From 5f1d1cb2e0295c9a8f3e6e1d866fa3a04f39ebcd Mon Sep 17 00:00:00 2001 From: Tachikoma Date: Mon, 3 Aug 2026 18:33:01 -0400 Subject: [PATCH] Bound CI build parallelism so five concurrent jobs stop starving the runner Run #31's sanitizers job failed, and not on anything in src/. The ASan build reached 100% and the runner's Docker daemon went away before ctest emitted a single line: "Cannot connect to the Docker daemon at unix:///var/run/docker.sock". The tree under test is identical to run #30's -- 9e5496f touched only this file -- and run #30's sanitizers job passed 112/112 in 83 s. What changed is that #30 was still losing akgl_build and coverage early, so #31 was the first push on which all five jobs did real work at the same time. All five say runs-on: ubuntu-latest, so all five share one runner, and every build step asked for a bare --parallel, i.e. nproc compilers each. The timestamps are unambiguous. Through 20:36:16 the sanitizers job links an executable in well under a second. akgl_build starts at 20:36:02 and begins compiling SDL, SDL_image, SDL_mixer, SDL_ttf, libccd and clay; mutation_test starts at 20:36:41. From 20:36:16 onward a single `Linking C executable` step takes one to two minutes -- a sixtyfold regression with no source change -- and at 20:49:55 the daemon is gone. ASan links are memory-hungry and the SDL tree is large; the runner ran out. The only lever on that is how many compiler and linker processes exist at once, so bound each build to 2. Worst case is now 8 rather than 5 x nproc. mutation_test drives its own builds through the harness and is left alone. Co-Authored-By: Claude Opus 5 (1M context) --- .gitea/workflows/ci.yaml | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/.gitea/workflows/ci.yaml b/.gitea/workflows/ci.yaml index 651d849..7c71781 100644 --- a/.gitea/workflows/ci.yaml +++ b/.gitea/workflows/ci.yaml @@ -44,10 +44,24 @@ jobs: run: | sudo apt-get update -y sudo apt-get install -y cmake gcc moreutils + # --parallel 2 rather than a bare --parallel, and that bound is measured + # rather than cautious. All five jobs in this file say runs-on: + # ubuntu-latest and land on the same runner, so a bare --parallel asks for + # nproc compilers *per job* and the runner is handed five times that at + # once. Run #30 never showed it because akgl_build and coverage were still + # dying early; run #31 was the first push on which all five did real work + # simultaneously, and the sanitizers job went from a 55-second link phase + # to a 14-minute one -- individual `Linking C executable` steps taking two + # minutes each, starting at the exact second akgl_build began its SDL tree + # -- before the runner's Docker daemon fell over outright and took the job + # with it. That is memory exhaustion, and the only lever on it is the + # number of concurrent compiler and linker processes. Applied at all four + # build sites for the same reason; mutation_test drives its own builds + # through the harness and is not bounded here. - name: build run: | cmake -S . -B build - cmake --build build --parallel + cmake --build build --parallel 2 # The suite is 78 cases: 41 golden files byte-compared against the Go # reference's own corpus (checked in at tests/reference/, see its README), # 9 local golden cases for verbs the reference never implemented, 25 unit @@ -98,7 +112,7 @@ jobs: cmake -S . -B build-asan \ -DAKBASIC_SANITIZE=ON \ -DCMAKE_BUILD_TYPE=Debug - cmake --build build-asan --parallel + cmake --build build-asan --parallel 2 ctest --test-dir build-asan --output-on-failure - run: echo "🍏 This job's status is ${{ job.status }}." @@ -138,7 +152,7 @@ jobs: cmake -S . -B build-coverage \ -DAKBASIC_COVERAGE=ON \ -DCMAKE_BUILD_TYPE=Debug - cmake --build build-coverage --parallel + cmake --build build-coverage --parallel 2 ctest --test-dir build-coverage --output-on-failure mkdir -p build-coverage/coverage gcovr --root . --filter 'src/.*' \ @@ -254,7 +268,7 @@ jobs: - name: build with libakgl run: | cmake -S . -B build-akgl -DAKBASIC_WITH_AKGL=ON - cmake --build build-akgl --parallel + cmake --build build-akgl --parallel 2 # Dummy video and audio drivers, set per test by CMakeLists rather than in # this job's environment, because an AKGL build of `basic` is now an SDL # program and the golden cases run *it*: forty-one real windows is not what