Speed

Each row compares shipcheck on an Apple silicon Mac with GitHub's hosted runners on the same commit, unless the notes say otherwise. GitHub's time runs from the run's creation to its end, so it includes the queue. To make your own runs faster, see speed up runs.

What makes a run fast

A first run is cold. It downloads the images, the toolchains and the packages, and builds every dependency, so it is often slower than GitHub.

Act mode

Measured on an idle Apple silicon Mac, Docker Desktop with 14 CPUs and 15.6 GiB, act 0.2.89.

RepositoryRunshipcheckGitHub ActionsDate
A large Rust app, 4 jobs, about 2,100 testsCold238 s116 s2026-10-23
A large Rust app, 4 jobs, about 2,100 testsWarm105 s124 s2026-10-23
A large Rust app, 4 jobs, about 2,100 testsWarm105 s115 s2026-10-23
pallets/flask, 9 jobsCold131 sabout 37 s2026-10-23
pallets/flask, 9 jobsWarm38 and 39 sabout 37 s2026-10-23

The Rust app's gitleaks job failed under act in every round, so its times are to that result. A warm run compiles only the app's own crate. The cold run also installs the toolchain and builds every dependency.

Host mode

On 2026-10-27, shipcheck init wrote host checks for some of the jobs of each repository below, and the rest stayed on GitHub. One repository ran at a time, with a load of 4 to 6 on 16 cores before each run and no other shipcheck run or build. Docker was down, so init kept every Docker job on GitHub. The GitHub column is the longest of those jobs, as the median over the last 10 successful PR heads.

RepositoryJobs shipcheck ranColdWarmCachedThose jobs on GitHub
shipcheck2 of 3134 s70 s0.36 s172 s
BurntSushi/ripgrep4 of 2330 s23 s0.48 s49.5 s
pallets/flask1 of 14failed every runfailed every run18 s
cli/cli1 of 1016 s15 s0.36 s31.5 s
curl/curl1 of 17810 s9.7 s1.05 s20 s

Host mode runs on your machine's OS. On the idle Mac of the act mode table, on 2026-10-23, the large Rust app's tests took 105 s on macOS against 16 s in act's Linux container.

Colima

The job is shipcheck's own ci.yml/test, which runs the fmt check, clippy and cargo test, with engine = "colima", run alone with shipcheck run --job test. Each version ran in its own empty SHIPCHECK_HOME, on the same Apple silicon Mac. These colima runs were measured on 2026-10-30 with the Mac's load between 2.6 and 4.1, so they are a first look. The time is the job's runner time.

VersionRunshipcheckLoad at startDate
v0.2.1Cold179 s4.02026-10-30
v0.2.1Warm190 s2.62026-10-30
v0.2.4Cold, builds the base VM once134 s2.62026-10-30
v0.2.4Warm, clones the base VM85 s4.12026-10-30

The same job on GitHub Actions, on ubuntu-latest with rust-cache, took 86 s of runner time, from 13:25:18 to 13:26:44 UTC (run 40881747310 on main, 2026-10-29). v0.2.4 boots each job's VM from a clone of a set-up base, fetches the actions on the Mac, and deletes the VM after the result, which is where the difference comes from. One more v0.2.1 warm run took 493 s while something else ran, and it is left out.

First look, measured on a busy machine

Other benchmarks or agents ran on the Mac during these runs, or the load was not recorded. The shipcheck times are rough.

Host mode

RepositoryRunshipcheckGitHub ActionsDate
A small Rust crate, fmt, clippy and testsFirst run, in the sandbox4.9 sabout 20 s2026-10-22
A small Rust crate, fmt, clippy and testsWarm, in the sandbox1.9 to 2.3 sabout 20 s2026-10-22
expressjs/express, lint and 1,261 testsWarm, in the sandbox3.4 to 6.8 s, one round failedabout 3.5 min2026-10-22
Another large Rust app, 5 checksWarm422 s413 s2026-10-23
Another large Rust app, 5 checksWarm, after a rebase onto main498 s413 s2026-10-23

Act mode

RepositoryRunshipcheckGitHub ActionsDate
A large Python app, 1 job, about 2,000 testsCold716 s, the retry passed367 s2026-10-21
A large Python app, 1 job, about 2,000 testsWarm468 s316 s2026-10-21
A large Python app, 1 job, about 2,000 testsWarm, after setup fixes274 to 341 s331 to 411 s2026-10-22
A large Python app, 1 job, about 2,000 testsWarm, tests in 6 shards162 and 195 s345 and 337 s2026-10-22
A small Rust crate, fmt, clippy and testsCold30 s38 s2026-10-22
A small Rust crate, fmt, clippy and testsWarm7 s21 and 33 s2026-10-22
pallets/flask, 9 jobsCold289 s36 s2026-10-22
pallets/flask, 9 jobsWarm63 and 64 s36 s2026-10-22
BurntSushi/ripgrep, 8 jobsCold284 s78 s2026-10-22
BurntSushi/ripgrep, 8 jobsWarm73 and 84 s78 s2026-10-22
junegunn/fzf, 1 jobCold462 s378 s2026-10-22
junegunn/fzf, 1 jobWarm381 and 385 s378 s2026-10-22
expressjs/express, 10 jobsCold220 s148 s, 96 s of it queued2026-10-22
colinhacks/zod, 5 jobsCold651 s177 s2026-10-22
colinhacks/zod, 5 jobsWarm588 s, one more round failed177 s2026-10-22
faker-ruby/faker, 6 jobsCold106 s29 s2026-10-22
faker-ruby/faker, 6 jobsWarm67 and 68 s29 s2026-10-22

On a 1-CPU Linux server

A rented server with 1 vCPU and 3.9 GB of memory, serving a small web app at the same time. It ran one job at a time.

RepositoryColdWarmGitHub ActionsDate
A small Rust crate, 1 job103 s19 and 20 s23 s2026-10-22
gin-gonic/gin, 11 jobs2,579 s513 and 519 s105 s2026-10-22
expressjs/express, 10 jobs1,235 s318 and 321 s148 s, 96 s of it queued2026-10-22

A job took about as long there as on GitHub's runner. GitHub runs 10 or 11 jobs at once, so a warm run there took about as long as the sum of GitHub's job times.

A tree already tested

RepositoryModeshipcheckGitHub ActionsDate
A large Python appAct0.13 sa full run2026-10-22
A small Rust crate and expressjs/expressHost0.26 sa full run2026-10-22

Previous: shipcheck.toml Next: Speed up runs