autback-benchmark measures multiple argv-based candidates against one exact worktree.
The checked-in LeapView specifications live under .autback/benchmarks/ and compare:
- native Docker Buildx, autback Buildx, and Depot for
DockerfileandDockerfile.site; - local Go and generic
autback execfor the two focused Testcontainers workloads.
Every specification uses one excluded warmup followed by five serial measured runs. It
passes identical trailing build/test arguments to every candidate and requires a clean
source worktree. Test samples execute in new detached worktrees so ignored derived files
and mutations from an earlier candidate cannot influence a later one. Image samples stay
in the same read-only source worktree because changing local-context paths defeats the
cache identity used by BuildKit and does not represent normal repeated builds. The runner
records the Git commit and a content fingerprint, preserves a log for every run, and writes
median plus nearest-rank p95 to summary.json. An unavailable optional
candidate is labeled unavailable; it is never replaced with an estimate or an older
cross-commit measurement.
Run a specification from the autback module, choosing an untracked output directory:
task benchmark:compare -- \
--spec ../.autback/benchmarks/testcontainers-lifecycle.json \
--output .tmp/benchmarks/testcontainers-lifecycle
DEPOT_PROJECT_ID=<project-id> task benchmark:compare -- \
--spec ../.autback/benchmarks/production-image.json \
--output .tmp/benchmarks/production-imageImage comparisons intentionally include --load, because both local development and
the current CI smoke tests consume the resulting image from the caller's Docker daemon.
The runner records end-to-end command latency. Provider-internal phase timing remains in
each raw log and must not be presented as a directly comparable metric unless all three
providers expose the same boundary.
The focused test specifications call repository-owned Taskfile workloads. Those tasks
force normal source generation before go test on both local and remote candidates.
autback itself has no LeapView preparation hook and ignored generated files are never added
to its generic source-transfer contract.
The controlled run on 2026-08-02 used one excluded warmup and five serial measured runs.
Both candidates in each comparison used the same clean commit, source fingerprint,
Dockerfile arguments, platform, tag, and --load output contract.
| Workload | Candidate | Median | p95 | Measured values |
|---|---|---|---|---|
| Generated Testcontainers lifecycle | local | 43.88 s | 44.46 s | 43.46, 44.19, 43.88, 44.46, 42.87 s |
| Generated Testcontainers lifecycle | autback | 72.90 s | 75.53 s | 71.13, 74.78, 72.90, 75.53, 72.51 s |
| Public site image | autback | 15.13 s | 16.90 s | 16.90, 15.13, 14.93, 14.62, 15.34 s |
| Public site image | Depot | 13.17 s | 199.45 s | 130.70, 199.45, 13.17, 7.88, 7.26 s |
| Production image | autback | 29.19 s | 30.34 s | 30.34, 29.19, 29.23, 28.82, 28.72 s |
| Production image | Depot | 31.00 s | 138.68 s | 138.68, 34.00, 31.00, 7.40, 7.80 s |
Every measured autback test run transferred 0 B of source. The CPX32 was approximately
1.66 times slower than the laptop for the generated Testcontainers command, reflecting
the worker's 3.5-vCPU job reservation plus the remote boundary. The result still moves
the sustained CPU load off the laptop, which is the product objective.
autback's BuildKit cache was immediately stable after its excluded warmup. Depot produced
the fastest eventual hot image loads—about 7 to 8 seconds—but its first measured runs
continued rebuilding while cache state settled, creating high p95 values in this sample.
The production/site difference in autback (29 versus 15 seconds) indicates that native
remote Buildx --load remains sensitive to output image size. Depot's optimized load
path largely removes that cost once fully hot.
No local image median is reported. OrbStack repeatedly rebuilt the source-generation
layer for an unchanged commit instead of producing a valid warm hit, so the runs were
stopped rather than mislabeled as cached performance. During diagnosis, adding **/.tmp
to .dockerignore reduced the context from 304 MB to 108 MB, but the constrained local
builder still did not retain the expensive layer reliably.
The compact machine-readable evidence is
leapview-provider-comparison/summary.json.
The LeapView consumer then replaced trusted --load jobs with the standard registry
handoff documented in Build, push, and smoke-test an immutable image.
GitHub Actions run 30742453481, attempt 2
reran the exact unchanged merge commit after the first complete run had populated the
cache. The remote builder pushed to GHCR, Buildx reported the immutable manifest digest,
and a separate Autback job exercised that exact digest on the worker.
| Workload | Warm build + push | Remote exact-digest check | Source upload | GitHub job |
|---|---|---|---|---|
| Public site image | 11.96 s | 5.50 s smoke | 0 B | 62 s |
| Production runner image | 9.54 s | — | — | part of production job |
| Production application image | 13.41 s | 56.11 s full qualification | 0 B | 139 s |
The GitHub job duration includes checkout, tool installation, Buildx setup, registry login, OIDC exchange, and post-job cleanup. The build column starts when Autback reports the native Buildx backend and ends when the digest-addressed manifest push completes. The production qualification includes image pull, smoke validation, API generation, remote CLI compilation, Compose startup, and browser checks; it is intentionally broader than a build benchmark.
This result removes the production image-size penalty seen in the earlier --load
comparison: the production build-and-push was 13.41 seconds instead of Autback's 29.19
second --load median. It is also below the earlier Depot 31.00 second median, while
Depot's final fully settled samples remained faster at roughly 7–8 seconds. The site
result was 11.96 seconds versus the earlier 15.13 second Autback and 13.17 second Depot
medians. These comparisons describe the observed runs, not a new five-sample
distribution; the committed evidence labels the hosted proof as a single warm repeat.
The exact runner digest from this proof was activated only after both image jobs passed.
A default-image verification reported Docker Compose v5.0.0 and completed in 1.665
seconds with 0 B uploaded. The prior runner digest remains in the audited image history
for one-command rollback.
The machine-readable evidence is
leapview-digest-push-warm/summary.json.
A dedicated, isolated workflow dispatch then ran one excluded warmup followed by five
serial samples per workload. GitHub Actions run
30743918183 used commit
ae2380d02832968842eff6d6fd6c972a855cb4fb. Each sample measured the complete Autback
CLI boundary: project-scoped OIDC authentication, scoped BuildKit mTLS setup, native
buildx --push, immutable digest capture, and a second remote job exercising that exact
digest.
| Workload | Build + push median | Build + push p95 | Exact-digest check median | Exact-digest check p95 | Total median | Total p95 |
|---|---|---|---|---|---|---|
| Public site image | 13.31 s | 13.51 s | 8.77 s | 51.67 s | 22.10 s | 65.18 s |
| Production image | 13.68 s | 13.94 s | 13.54 s | 13.94 s | 27.46 s | 27.69 s |
The production samples are tightly clustered. Four of five site checks completed in 8.76–9.19 seconds; the first measured site check took 51.67 seconds while other work was active on the single CPX32. The table intentionally retains that contention tail. It shows that cached builds are stable while exact-digest execution latency still depends on shared-worker capacity and should be protected with queueing or concurrency limits.
The full sorted distributions and every digest are in
controlled-summary.json,
with per-run boundaries in
controlled-results.ndjson.
The generic service E2E on 2026-08-01 ran a project-selected pinned Go image through
Connect/HTTPS, job-scoped CAS mTLS, private Swarm scheduling, and Testcontainers. Its
repeat input upload was 0 B; the final cached end-to-end sample was 2.800 seconds. A native
Buildx build then reached BuildKit through a separate build-scoped certificate and hit
its cached layer. The committed machine-readable result is
evidence/service-local/proof.json; raw logs are
intentionally retained only as local operational output.
This is a functional boundary benchmark on the constrained local OrbStack VM, not a fair capacity comparison with the developer laptop or CPX32. The CPX32 warm workload numbers below remain the useful remote compute baseline.
The final generic service proof on the existing Hetzner CPX32 completed its warm run in
3.893 seconds with 0 B uploaded; its preceding sample was 3.807 seconds. Testcontainers,
timeout, cancellation, durable FIFO queueing, and native BuildKit mTLS all passed. An
earlier first deployment sample uploaded only 590 bytes because the prior legacy
benchmarks had already populated most CAS/image content. The committed proof is
evidence/service/proof.json.
Measured on 2026-08-01 at LeapView merge commit
23248fa0c4ebbef579b10f090a7ad26e7ccc67f3 using the existing Hetzner CPX32:
- worker: 4 vCPU, 8 GB RAM;
- job reservation and limit: 2.5 vCPU, 5 GB RAM;
- one priming run excluded, followed by five serial measured runs;
- source snapshot: 1,921 files, 26.2 MiB;
- every measured run transferred
0 Bthrough CAS; go test -count=1forced the tests to execute while retaining dependency/build caches;- pinned Docker and Testcontainers images were already present for measured runs.
| Workload | End-to-end median | End-to-end p95 | Remote median | autback boundary median |
|---|---|---|---|---|
| MinIO Parquet refresh contract | 29.04 s | 29.70 s | 24.53 s | 4.51 s |
| Testcontainers qualification lifecycle | 21.91 s | 22.41 s | 17.42 s | 4.52 s |
“End-to-end” starts before source selection/CAS negotiation and stops after the CLI has reported the terminal result. “Remote” is the Swarm task lifetime. “autback boundary” is their difference and, for this pre-service client, included local input hashing, zero-byte CAS negotiation, SSH setup, Swarm submission/status, and final result retrieval. Current clients use only the Connect/HTTPS service boundary measured in the preceding sections.
The committed five-run summaries are
leapview-minio-warm/summary.json
and
leapview-testcontainers-lifecycle-warm/summary.json.
Per-run logs are intentionally retained only as local operational output.
The benchmark does not report a cold-cache number. Source-generation and build-tag configuration were corrected during initial setup, which seeded parts of CAS, Docker, and Go caches. Clearing shared worker caches solely to manufacture a cold number would disturb the useful POC state and is not necessary for the primary warm-cache decision.
LeapView's build-only generated Go packages are intentionally gitignored. The benchmark
ran the normal source-generation step once and explicitly included those derived files in
the immutable input snapshot; generation time is outside the measurements. LeapView's
project image and repository command must make that preparation reproducible without
weakening Git ignore semantics. The project OCI image supplies the toolchain, and a
repository-owned command such as task test performs generation and testing inside one
remote job.
The first full qualification attempt also found that Debian Bookworm's docker.io CLI
only supported API 1.41, while the worker's Docker 29 daemon requires API 1.44 or newer.
The then-current runner was corrected to copy the official digest-pinned Docker 29.1.3
CLI. After that upgrade, the complete merged qualification lifecycle passed both its
docker-cli and testcontainers implementations remotely in one job. Autback no longer
ships that language-specific runner; the same dependency now belongs in LeapView's OCI
project image.
This legacy run established a roughly 4.5-second boundary. The current service proof above replaced the SSH client path and reduced that boundary. More CPU can reduce Go compilation and test execution, but it does not remove fixed CAS, control-plane, or Swarm lifecycle latency.
The final warm-cache cutover run executed the repository's unmodified task ci contract
on the existing CPX32 in 652.317 seconds (10m52.317s). CAS transferred 0 B. This was not
a reduced benchmark: generation verification, browser and Go suites, Testcontainers,
vet, race checks, route QA, and both Terraform deployment validations all passed. The
runner reserved 3.5 vCPU and 6 GiB from the 4-vCPU/8-GiB worker.
The machine-readable result is
service/leapview-cutover.json, and the
operational cutover and rollback procedure is in
leapview-cutover.md.