Benchmarks

jerboa against Docker

18 comparisons on two machines, measured in October 2026 while preparing v0.55.0. jerboa comes out ahead in 9, Docker in 5, and the rest are within 5 %.

Results

macOS Apple M5, 10 cores, 16 GB, macOS 26

jerboa
Firecracker on Hypervisor.framework; VMs with 4 vCPU and 2 GiB
Docker
Docker Desktop 29.7.2, quit while jerboa ran
Startup run --rm echo hello Wall time of a one-shot run, mean of 10 · lower is better
22 % faster
CPU sysbench cpu, 4 threads Events per second
6 % faster
Memory sysbench memory, 1K blocks 4 threads
even
Disk fio random read 4k 4 jobs × 1 GiB, 60 s
6.3× faster
Disk fio random write 4k 4 jobs × 1 GiB, 60 s
even
Disk fio sequential write + fsync 1 MiB blocks, 1000 MB
47 % slower
Network iperf3 host → VM TCP through a published port
even
Network iperf3 VM → host TCP through a published port
40 % slower
Apps Redis SET redis-benchmark through a published port
38 % faster
Apps HTTP, Go server wrk, 4 threads, 100 connections
91 % faster

Docker Desktop runs all containers inside one Linux VM; jerboa boots one VM per app on Hypervisor.framework.

Linux Xeon E5-2620 (2012), nested KVM guest with 2 vCPU and 4 GB

jerboa
Firecracker; VMs with 2 vCPU and 1 GiB; 2 MiB huge pages reserved for both sides
Docker
Docker 29.1.3
Startup run --rm echo hello Wall time of a one-shot run, mean of 10 · lower is better
2.1× faster
CPU sysbench cpu, 4 threads Events per second
even
Disk fio random read 4k 4 jobs × 1 GiB, 60 s
2.5× faster
Disk fio random write 4k 4 jobs × 1 GiB, 60 s
46 % faster
Disk fio sequential write + fsync 1 MiB blocks, 1000 MB
15 % slower
Apps Redis SET, client on the host Published port, kernel NAT
15 % faster
Apps Redis SET, client on the LAN Published port, --port-publish nat-lan
37 % slower
Apps HTTP, Go server wrk, 4 threads, 100 connections
7 % slower

This host is itself a VM without APICv, so every guest exit costs 50–120 µs instead of 1–2 µs. That penalizes jerboa’s VMs and not Docker’s containers.

How it was measured

  • Same binaries. Each tool is built once per architecture and runs unchanged in both runtimes. jerboa imports the same Debian image Docker runs, with jerboa pkg from-docker.
  • Interleaved. Rounds alternate between the runtimes and rotate their order, so heat and background load don’t favor one side. Only one runtime runs at a time.
  • Medians. Every figure is the median of at least three runs. All samples are kept in the engine’s benchmark notes, under the series name in the Sources table.
  • Limits. In the battery (start-up, CPU, memory, disk) Docker runs without limits, as in the original benchmark. In the network and application series its CPU and memory limits match the jerboa VM’s.
  • Tooling. The test battery follows OneUptime’s container benchmark (sysbench, fio, iperf3, wrk, redis-benchmark). Network and application series use the same tools.

What is left out

macOS

  • Cold start: Docker’s number includes pulling node:20-alpine, so the comparison is not like for like.
  • Memory with 1 MiB blocks: with 4 threads on one shared buffer the result depends on where macOS places the vCPUs. With 1 thread both reach about 52 GB/s.
  • stress-ng: it needs fork(), which a unikernel does not provide.

Linux

  • sysbench memory: Docker measured 569 MiB/s with 1K blocks on this host, against 14.6 GB/s with 1 MiB blocks. That result has no explanation yet, so no comparison is published.
  • Cold start: Docker’s number includes pulling node:20-alpine.
  • stress-ng: it needs fork(), which a unikernel does not provide.

Sources

HostTestDockerjerboaUnitSeries
macOSrun --rm echo hello131107msfull-1008
macOSsysbench cpu, 4 threads54,83258,146ev/sfull-1008
macOSsysbench memory, 1K blocks5,9545,693MiB/sfull-1008
macOSfio random read 4k29,746187,900IOPSfull-1008
macOSfio random write 4k45,60047,600IOPSfull-1008
macOSfio sequential write + fsync4,6732,475MiB/sfull-1008
macOSiperf3 host → VM1313Gbit/sgw-ab7
macOSiperf3 VM → host27.716.5Gbit/sgw-ab7
macOSRedis SET71,00098,000req/sgw-ab7
macOSHTTP, Go server40,60077,700req/sgw-ab7
Linuxrun --rm echo hello2,1751,019msfull-1008
Linuxsysbench cpu, 4 threads1,2571,204ev/sfull-1008
Linuxfio random read 4k171421IOPSfull-1008
Linuxfio random write 4k4,6116,746IOPSfull-1008
Linuxfio sequential write + fsync142121MiB/sfull-1008
LinuxRedis SET, client on the host10,43511,962req/sapp-ab1
LinuxRedis SET, client on the LAN18,30011,463req/slan-ab1
LinuxHTTP, Go server6,6966,220req/sapp-ab1

Run it yourself

The engine ships jerboa-bench, which packages one static test service as a jerboa image and as a FROM scratch Docker image, checks that both hold the same binary, and shuffles the runs.

shell
go build -o dist/jerboa-bench ./cmd/jerboa-bench
dist/jerboa-bench --jerboa dist/jerboa \
  --runtime fc=jerboa,network=bench,layout=compact \
  --runtime docker=docker \
  --runs 30 --warmup 3 --out bench.json
Read the jerboa-bench reference