Skip to content

ci(e2e): speed up e2e job via Ginkgo proc oversubscription - #2085

Merged
0xERR0R merged 3 commits into
mainfrom
perf/e2e-test-speedup
Jun 5, 2026
Merged

0xERR0R merged 3 commits into
mainfrom
perf/e2e-test-speedup

Conversation

@0xERR0R

@0xERR0R 0xERR0R commented Jun 5, 2026

Copy link
Copy Markdown
Owner

What

The e2e-test target runs Ginkgo with -p (one process per core). e2e specs
are dominated by container startup and health-check waits, not CPU — across
the suite, ~1663s of summed spec runtime compresses to ~244s wall-clock, and
even trivial specs cost 15–30s because each one spins up a fresh Docker network

  • blocky (+ upstream) container via BeforeEach. That means we can safely run
    more Ginkgo processes than the runner has cores.

This adds a GINKGO_E2E_PROCS knob (default -p, so local runs are unchanged)
and sets --procs=8 in CI to oversubscribe the 4-core ubuntu-latest runner.

Measured impact (CI make (e2e-test) job)

duration
Baseline (-p) ~6m45s
--procs=8 4m27s (−34%, ~2m18s)

Verified across 3 CI runs: 137/137 specs pass, 0 skips, 0 flakes — the higher
parallelism does not trigger any IPv6 fixed-subnet / network-collision skips.

Local reference (8-core): 244s (-p) → 185s (--procs=16).

Notes

  • Local behaviour is unchanged (GINKGO_E2E_PROCS defaults to -p); only CI
    overrides it.
  • GINKGO_PROCS: --procs=1 in CI only ever applied to the test/race
    targets, never to e2e — so this is not a regression of any prior serialization.
  • I also trialed a type=gha Docker build cache but dropped it: it silently
    no-ops with a raw docker buildx build in a plain run: step (the backend
    needs ACTIONS_RUNTIME_TOKEN, which only docker/build-push-action injects),
    and the e2e image build is mostly per-commit recompile + image load anyway.

Please squash-merge (the branch has an extra throwaway commit from
measuring warm-cache build times).

0xERR0R added 3 commits June 5, 2026 09:23
The e2e specs are dominated by container startup and health-check waits
rather than CPU, so running more Ginkgo processes than the runner has
cores improves wall-clock time. Locally this cut a full run from 244s
(-p, 8 procs/8 cores) to 185s (--procs=16).

- Add GINKGO_E2E_PROCS (default -p, unchanged locally); CI sets --procs=8.
- Add DOCKER_E2E_CACHE_FLAGS so CI can reuse e2e build layers via the
  GitHub Actions cache (type=gha), mirroring development-docker.yml.

Local default behaviour is unchanged; both knobs are CI-only overrides.
No-op commit to measure e2e build time with the GitHub Actions cache
warm (populated by the previous run).
The type=gha cache flags silently no-op with a raw 'docker buildx build'
in a plain run: step (no ACTIONS_RUNTIME_TOKEN/ACTIONS_CACHE_URL exposed),
so the build recompiled from scratch on warm runs and saved nothing.
Removing the flags to avoid GitHub Actions cache-storage pressure.

The win is the Ginkgo proc oversubscription (--procs=8 on the 4-core
runner): e2e-test job 6m45s -> ~4m40s (-30%), 137/137 specs, 0 skips.
Copilot AI review requested due to automatic review settings June 5, 2026 07:47
@0xERR0R 0xERR0R added this to the v0.32.0 milestone Jun 5, 2026
@0xERR0R 0xERR0R added the 🧰 technical debts Technical debts, refactoring label Jun 5, 2026
@0xERR0R
0xERR0R enabled auto-merge (squash) June 5, 2026 07:48

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR speeds up the CI e2e-test job by making Ginkgo’s parallelism configurable for e2e runs and oversubscribing processes on GitHub Actions runners where e2e time is dominated by container startup/health-check waits rather than CPU.

Changes:

  • Add GINKGO_E2E_PROCS Makefile knob (default -p) to control e2e Ginkgo parallelism without changing local defaults.
  • Update e2e Makefile targets to use GINKGO_E2E_PROCS instead of hardcoding -p.
  • Set GINKGO_E2E_PROCS=--procs=8 in the GitHub Actions workflow env to speed up CI.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
Makefile Introduces GINKGO_E2E_PROCS and wires it into e2e-test and e2e-test-coverage Ginkgo invocations.
.github/workflows/makefile.yml Sets GINKGO_E2E_PROCS in CI to oversubscribe Ginkgo processes for faster e2e runs.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@codecov

codecov Bot commented Jun 5, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 86.21%. Comparing base (b82199b) to head (b51b3c4).

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #2085   +/-   ##
=======================================
  Coverage   86.21%   86.21%           
=======================================
  Files         112      112           
  Lines        8367     8367           
=======================================
  Hits         7214     7214           
  Misses        932      932           
  Partials      221      221           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@0xERR0R
0xERR0R merged commit 1c9f717 into main Jun 5, 2026
24 checks passed
@0xERR0R
0xERR0R deleted the perf/e2e-test-speedup branch June 5, 2026 07:53
dadezzz pushed a commit to dadezzz/infra_docker-compose that referenced this pull request Jun 20, 2026
This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [ghcr.io/0xerr0r/blocky](https://github.com/0xERR0R/blocky) | minor | `v0.31.0` → `v0.32.0` |

---

### Release Notes

<details>
<summary>0xERR0R/blocky (ghcr.io/0xerr0r/blocky)</summary>

### [`v0.32.0`](https://github.com/0xERR0R/blocky/releases/tag/v0.32.0)

[Compare Source](0xERR0R/blocky@v0.31.0...v0.32.0)

#### Changelog

##### Features

- [`c851293`](0xERR0R/blocky@c851293): feat(blocking): log the matched rule in the block reason ([#&#8203;2091](0xERR0R/blocky#2091)) ([@&#8203;0xERR0R](https://github.com/0xERR0R))
- [`87be127`](0xERR0R/blocky@87be127): feat(cache): Shard the result cache to remove the single-lock read ceiling ([#&#8203;2097](0xERR0R/blocky#2097)) ([@&#8203;0xERR0R](https://github.com/0xERR0R))
- [`7c6da15`](0xERR0R/blocky@7c6da15): feat(config): structurally merge config folder files ([#&#8203;1827](0xERR0R/blocky#1827)) ([#&#8203;2112](0xERR0R/blocky#2112)) ([@&#8203;0xERR0R](https://github.com/0xERR0R))
- [`e7958e0`](0xERR0R/blocky@e7958e0): feat(lists): opt-in on-disk download cache with conditional revalidation ([#&#8203;2087](0xERR0R/blocky#2087)) ([@&#8203;0xERR0R](https://github.com/0xERR0R))
- [`b82199b`](0xERR0R/blocky@b82199b): feat(querylog): ignore domains (exact/wildcard/regex) in query log ([#&#8203;2084](0xERR0R/blocky#2084)) ([@&#8203;0xERR0R](https://github.com/0xERR0R))
- [`bee2d8b`](0xERR0R/blocky@bee2d8b): feat(resolver): UDP-first plain-DNS upstream and EDNS0 buffer floor ([#&#8203;2100](0xERR0R/blocky#2100)) ([@&#8203;0xERR0R](https://github.com/0xERR0R))
- [`0b70e5c`](0xERR0R/blocky@0b70e5c): feat(resolver): add DNS rebinding protection ([#&#8203;2111](0xERR0R/blocky#2111)) ([@&#8203;0xERR0R](https://github.com/0xERR0R))
- [`1b8e08a`](0xERR0R/blocky@1b8e08a): feat(resolver): pool DoT connections and enable TLS session resumption ([#&#8203;2098](0xERR0R/blocky#2098)) ([@&#8203;0xERR0R](https://github.com/0xERR0R))
- [`4018d9e`](0xERR0R/blocky@4018d9e): feat: in-memory statistics subsystem with /api/stats REST endpoint ([#&#8203;2093](0xERR0R/blocky#2093)) ([@&#8203;0xERR0R](https://github.com/0xERR0R))
- [`7abca44`](0xERR0R/blocky@7abca44): feat: support PROXY protocol on proxied DoT/DoH listeners ([#&#8203;2094](0xERR0R/blocky#2094)) ([@&#8203;kastakhov](https://github.com/kastakhov))

##### Bug fixes

- [`2496d12`](0xERR0R/blocky@2496d12): fix(dnssec): close DNSSEC validation bypass & cache-scope pollution (GHSA-x845-2f78-7v36) ([#&#8203;2119](0xERR0R/blocky#2119)) ([@&#8203;0xERR0R](https://github.com/0xERR0R))
- [`06555e0`](0xERR0R/blocky@06555e0): fix(metrics): bound reason label cardinality for blocked responses ([#&#8203;2114](0xERR0R/blocky#2114)) ([@&#8203;0xERR0R](https://github.com/0xERR0R))
- [`e0ea9b3`](0xERR0R/blocky@e0ea9b3): fix(resolver): eliminate recursive RLock deadlock in blocking group resolution ([#&#8203;2106](0xERR0R/blocky#2106)) ([@&#8203;0xERR0R](https://github.com/0xERR0R))
- [`80f742e`](0xERR0R/blocky@80f742e): fix(server): answer browser CORS preflights for custom headers and Private Network Access ([#&#8203;2109](0xERR0R/blocky#2109)) ([@&#8203;0xERR0R](https://github.com/0xERR0R))
- [`9702c8f`](0xERR0R/blocky@9702c8f): fix(stats): populate allow/denylist counts in /api/stats at startup ([#&#8203;2113](0xERR0R/blocky#2113)) ([@&#8203;0xERR0R](https://github.com/0xERR0R))

##### Build and dependencies

- [`821e378`](0xERR0R/blocky@821e378): build(deps): bump codecov/codecov-action from 6 to 7 ([#&#8203;2089](0xERR0R/blocky#2089)) ([@&#8203;dependabot](https://github.com/dependabot)\[bot])
- [`d63f84b`](0xERR0R/blocky@d63f84b): build(deps): bump github.com/0xERR0R/expiration-cache from 0.1.0 to 0.2.0 ([#&#8203;2095](0xERR0R/blocky#2095)) ([@&#8203;dependabot](https://github.com/dependabot)\[bot])
- [`81f2b2a`](0xERR0R/blocky@81f2b2a): build(deps): bump github.com/onsi/ginkgo/v2 from 2.29.0 to 2.30.0 ([#&#8203;2108](0xERR0R/blocky#2108)) ([@&#8203;dependabot](https://github.com/dependabot)\[bot])
- [`9c5abdf`](0xERR0R/blocky@9c5abdf): build(deps): bump github.com/onsi/ginkgo/v2 from 2.30.0 to 2.31.0 ([#&#8203;2116](0xERR0R/blocky#2116)) ([@&#8203;dependabot](https://github.com/dependabot)\[bot])
- [`6c0ec5f`](0xERR0R/blocky@6c0ec5f): build(deps): bump github.com/onsi/gomega from 1.41.0 to 1.42.0 ([#&#8203;2115](0xERR0R/blocky#2115)) ([@&#8203;dependabot](https://github.com/dependabot)\[bot])
- [`4beb9fe`](0xERR0R/blocky@4beb9fe): build(deps): bump github.com/quic-go/quic-go from 0.59.1 to 0.60.0 ([#&#8203;2090](0xERR0R/blocky#2090)) ([@&#8203;dependabot](https://github.com/dependabot)\[bot])
- [`8fe2202`](0xERR0R/blocky@8fe2202): build(deps): bump golang.org/x/net from 0.55.0 to 0.56.0 ([#&#8203;2101](0xERR0R/blocky#2101)) ([@&#8203;dependabot](https://github.com/dependabot)\[bot])
- [`52fa6a4`](0xERR0R/blocky@52fa6a4): build(deps): bump golang.org/x/sys from 0.45.0 to 0.46.0 ([#&#8203;2096](0xERR0R/blocky#2096)) ([@&#8203;dependabot](https://github.com/dependabot)\[bot])

##### Misc

- [`1c9f717`](0xERR0R/blocky@1c9f717): ci(e2e): speed up e2e job via Ginkgo proc oversubscription ([#&#8203;2085](0xERR0R/blocky#2085)) ([@&#8203;0xERR0R](https://github.com/0xERR0R))
- [`8d49922`](0xERR0R/blocky@8d49922): ci: cross-compile multi-arch docker image instead of QEMU emulation ([#&#8203;2081](0xERR0R/blocky#2081)) ([@&#8203;0xERR0R](https://github.com/0xERR0R))
- [`355a9a1`](0xERR0R/blocky@355a9a1): docs(grafana): redesign Grafana dashboard and update integration guide ([#&#8203;2110](0xERR0R/blocky#2110)) ([@&#8203;0xERR0R](https://github.com/0xERR0R))
- [`c791e80`](0xERR0R/blocky@c791e80): perf(e2e): probe blocky healthcheck at 250ms during start period ([#&#8203;2086](0xERR0R/blocky#2086)) ([@&#8203;0xERR0R](https://github.com/0xERR0R))
- [`a0fb375`](0xERR0R/blocky@a0fb375): perf(lists): speed up blocklist loading (cache build + parsing) ([#&#8203;2083](0xERR0R/blocky#2083)) ([@&#8203;0xERR0R](https://github.com/0xERR0R))
- [`316b073`](0xERR0R/blocky@316b073): perf(resolver): pre-classify client groups to cut per-query allocations ([#&#8203;2103](0xERR0R/blocky#2103)) ([@&#8203;0xERR0R](https://github.com/0xERR0R))
- [`d502806`](0xERR0R/blocky@d502806): perf(server): let Truncate decide response compression ([#&#8203;2102](0xERR0R/blocky#2102)) ([@&#8203;0xERR0R](https://github.com/0xERR0R))
- [`8b32512`](0xERR0R/blocky@8b32512): test(e2e): de-flake PROXY protocol and upstream init.strategy specs ([#&#8203;2099](0xERR0R/blocky#2099)) ([@&#8203;0xERR0R](https://github.com/0xERR0R))

***

#### ❤️ Support Blocky

Blocky is free and open source, developed in my spare time — no telemetry, no ads, no hidden
filtering. If it's useful to you, please consider supporting its continued development:

[GitHub Sponsors](https://github.com/sponsors/0xERR0R) ·
[thanks.dev](https://thanks.dev/u/gh/0xERR0R) ·
[Liberapay](https://liberapay.com/spx01) ·
[Ko-fi](https://ko-fi.com/0xerr0r) ·
[PayPal](https://paypal.me/spx01)

Thank you to everyone supporting Blocky! 🙏

</details>

---

### Configuration

📅 **Schedule**: (UTC)

- Branch creation
  - At any time (no schedule defined)
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yMjIuMSIsInVwZGF0ZWRJblZlciI6IjQzLjIyMi4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🧰 technical debts Technical debts, refactoring

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants