When running beats downloading
When running beats downloading
If a download would take longer than running the task, vx runs the task. 500 remote hits finish in 1.15 s instead of 3.12 s.
One synthetic task graph, each tool in its own native config, every number one command away.
Every number on our benchmark page is one command away. Here is the time each runner adds on top of the tasks, on one 9,603-task graph:
| Runner | Cold build overhead | Nothing changed | Cold build CPU |
|---|---|---|---|
| vx | 6.68 s | 559 ms | 42.19 s |
| Turborepo | 11.18 s | 689 ms | 1 min 19 s |
| Nx | 3 min 12 s | 12.07 s | 5 min 31 s |
| Vite Task | 8.51 s | 10.71 s | 24.17 s |
Synthetic monorepo, 1,601 projects, 9,603 tasks, 30 levels · build 300 ms, test and typecheck 150 ms, lint 75 ms, publish 30 ms · concurrency 10
Measured: vx 0.0.0 @ ee4c63a57 on 2026-11-12, Turborepo 2.11.10 on 2026-11-12, Nx 24.0.2 on 2026-11-12, Vite Task 1.4.0 on 2026-11-12; linux x64, 4 cores (AMD EPYC 7763 64-Core Processor), 16 GB.
Lower is better. A cold build’s tasks alone take 1 min 53 s with an ideal schedule. With nothing changed the ideal is 0, so all of that time is the runner.
The table is filled from the latest run when the site is built: each change to vx re-measures vx, and a new Turborepo, Nx or Vite Task pin re-measures that tool.
$ bun private/vx-bench/compare.ts 3Every task is a sleep of a fixed length, so the numbers measure the
runner, not a compiler. Each runner runs the graph cold, with nothing
changed, and with outputs restored.
The site takes its rows from vx run @vzn/vx-bench#site.numbers: one
task per runner, each on a machine of its own.
flowchart LR G[generate.ts: one graph] --> V[vx config] G --> T[turbo.json] G --> N[Nx targets] G --> VT[vite.config.ts] V & T & N & VT --> C[compare.ts: one runner at a time]
| Rule | Why |
|---|---|
| each tool in its native config | Turborepo turbo.json, Nx nx:run-commands targets, Vite Task vite.config.ts |
| concurrency 10 for all | same parallelism |
vx as the compiled binary, from a vx lock snapshot |
what users install and CI runs |
| CI mode | as CI runs them |
| one runner at a time | no daemon idle-contends for CPU |
| no edit row | Nx needs its daemon for one, and CI doesn’t run it |
Turbo and Nx run as they would in CI (CI=1: Nx’s daemon off, and
Turbo uses none for turbo run).
The first two columns are wall time. The third is the runner’s own CPU time, minus the tasks. A daemon that outlives the run isn’t counted, so Turborepo’s and Nx’s CPU are lower bounds.
Every row is on Benchmarks.
Every change to vx’s warm path ships with a number measured like this: before and after interleaved, fastest of N, “before” built from its own git worktree.
If a number here doesn’t reproduce on your machine, please file a bug.
More at vznjs.github.io/vx.