quickstart →

Fastest GitHub Actions runners: disk I/O.

fio inside the job workspace of 93 runners from 9 providers, 2 to 12 vCPU. These are the disk's limits. A build goes through the Linux page cache and often never reaches them, so a large gap here can be no gap on a build.

Fastest QD1 read, x64 at 4 vCPU 78,187 Namespace 4x8 (4 vCPU) · reads/s
Fastest QD1 read, arm64 at 4 vCPU 23,747 Blacksmith 4 vCPU · reads/s
GitHub at 4 vCPU 7,479 x64 QD1 reads/s on GitHub 4-core
Fastest synced writes, x64 at 4 vCPU 18,087 Namespace 4x8 · writes/s
tmpfs, for scale 1.2M QD1 reads/s on RunsOn m8a.2xlarge · tmpfs: the workspace in RAM

Latency per provider

Each provider's best disk, RunsOn once per storage (the Storage pill). QD1 is one 4k read at a time: what a database or a cold read pays. Most build steps batch their I/O through the page cache. tmpfs is RAM, not a disk: add it to see the gap on the same scale.

QD1 random readx64 · 4k, one request in flight · IOPS, higher is better
  1. Blacksmith2 vCPUVM disk80,883, p99 17 µs, ×1.00
  2. Namespace8 vCPU8x32 · VM disk78,677, p99 12 µs, ×0.97
  3. StarSling8 vCPUVM disk56,745, p99 17 µs, ×0.70
  4. Avrea2 vCPUVM disk44,589, p99 17 µs, ×0.55
  5. Warpbuild8 vCPUVM disk27,503, p99 48 µs, ×0.34
  6. RunsOn4 vCPUi7i.xlarge · local NVMe11,437, p99 301 µs, ×0.14
  7. Ubicloud8 vCPUpremium · VM disk10,785, p99 167 µs, ×0.13
  8. GitHub8 vCPUVM disk7,942, p99 202 µs, ×0.10
  9. RunsOn4 vCPUm8azn.xlarge · EBS gp31,815, p99 848 µs, ×0.02
  10. AWS CodeBuild4 vCPUmedium · EBS1,766, p99 717 µs, ×0.02

Blacksmith and Namespace lead x64 QD1 read, within 5% (80,883 and 78,677).tmpfs for scale: 1,153,230 on RunsOn m8a.2xlarge · tmpfs.

Synced writesx64 · 4k + fdatasync · IOPS, higher is better
  1. Blacksmith2 vCPUVM disk · nobarrier18,654, p99 25 µs, ×1.00
  2. Namespace8 vCPU8x32 · VM disk18,198, p99 20 µs, ×0.98
  3. RunsOn2 vCPUi7i.large · local NVMe13,194, p99 34 µs, ×0.71
  4. Avrea4 vCPUVM disk8,676, p99 35 µs, ×0.47
  5. GitHub2 vCPUVM disk · nobarrier4,559, p99 117 µs, ×0.24
  6. StarSling8 vCPUVM disk3,260, p99 29 µs, ×0.17
  7. Ubicloud2 vCPUpremium · VM disk2,683, p99 1,794 µs, ×0.14
  8. Warpbuild8 vCPUVM disk2,133, p99 109 µs, ×0.11
  9. AWS CodeBuild2 vCPUsmall · EBS571, p99 987 µs, ×0.03
  10. RunsOn2 vCPUm8azn.large · EBS gp3 · nobarrier542, p99 987 µs, ×0.03

Blacksmith and Namespace lead x64 synced writes, within 5% (18,654 and 18,198).volatile and nobarrier mounts make each flush cheaper by making it less durable.

QD1 random readx64 at 2 vCPU · 4k, one request in flight · IOPS, higher is better
  1. Blacksmith2 vCPUVM disk80,883, p99 17 µs, ×1.00
  2. Namespace2 vCPU2x8 · VM disk77,442, p99 13 µs, ×0.96
  3. Avrea2 vCPUVM disk44,589, p99 17 µs, ×0.55
  4. Warpbuild2 vCPUVM disk24,646, p99 59 µs, ×0.30
  5. RunsOn2 vCPUi7i.large · local NVMe11,384, p99 313 µs, ×0.14
  6. GitHub2 vCPUVM disk7,544, p99 222 µs, ×0.09
  7. Ubicloud2 vCPUpremium · VM disk6,564, p99 1,597 µs, ×0.08
  8. RunsOn2 vCPUc8a.large · EBS gp31,812, p99 741 µs, ×0.02
  9. AWS CodeBuild2 vCPUsmall · EBS1,760, p99 774 µs, ×0.02

Blacksmith and Namespace lead x64 2 vCPU QD1 read, within 5% (80,883 and 77,442).tmpfs for scale: 1,153,230 on RunsOn m8a.2xlarge · tmpfs.

Synced writesx64 at 2 vCPU · 4k + fdatasync · IOPS, higher is better
  1. Blacksmith2 vCPUVM disk · nobarrier18,654, p99 25 µs, ×1.00
  2. Namespace2 vCPU2x8 · VM disk17,813, p99 23 µs, ×0.95
  3. RunsOn2 vCPUi7i.large · local NVMe13,194, p99 34 µs, ×0.71
  4. Avrea2 vCPUVM disk8,416, p99 34 µs, ×0.45
  5. GitHub2 vCPUVM disk · nobarrier4,559, p99 117 µs, ×0.24
  6. Ubicloud2 vCPUpremium · VM disk2,683, p99 1,794 µs, ×0.14
  7. Warpbuild2 vCPUVM disk2,084, p99 117 µs, ×0.11
  8. AWS CodeBuild2 vCPUsmall · EBS571, p99 987 µs, ×0.03
  9. RunsOn2 vCPUm8azn.large · EBS gp3 · nobarrier542, p99 987 µs, ×0.03

Blacksmith and Namespace lead x64 2 vCPU synced writes, within 5% (18,654 and 17,813).volatile and nobarrier mounts make each flush cheaper by making it less durable.

QD1 random readx64 at 4 vCPU · 4k, one request in flight · IOPS, higher is better
  1. Namespace4 vCPU4x8 · VM disk78,187, p99 13 µs, ×1.00
  2. Blacksmith4 vCPUVM disk71,607, p99 14 µs, ×0.92
  3. StarSling4 vCPUVM disk55,952, p99 18 µs, ×0.72
  4. Avrea4 vCPUVM disk43,283, p99 20 µs, ×0.55
  5. Warpbuild4 vCPUVM disk21,207, p99 58 µs, ×0.27
  6. RunsOn4 vCPUi7i.xlarge · local NVMe11,437, p99 301 µs, ×0.15
  7. Ubicloud4 vCPUstandard · VM disk9,145, p99 465 µs, ×0.12
  8. GitHub4 vCPUnetwork disk7,479, p99 210 µs, ×0.10
  9. RunsOn4 vCPUm8azn.xlarge · EBS gp31,815, p99 848 µs, ×0.02
  10. AWS CodeBuild4 vCPUmedium · EBS1,766, p99 717 µs, ×0.02

Fastest x64 4 vCPU QD1 read: Namespace (78,187), ahead of Blacksmith (71,607).tmpfs for scale: 1,153,230 on RunsOn m8a.2xlarge · tmpfs.

Synced writesx64 at 4 vCPU · 4k + fdatasync · IOPS, higher is better
  1. Namespace4 vCPU4x8 · VM disk18,087, p99 21 µs, ×1.00
  2. Blacksmith4 vCPUVM disk · nobarrier17,872, p99 26 µs, ×0.99
  3. RunsOn4 vCPUi7i.xlarge · local NVMe12,559, p99 36 µs, ×0.69
  4. Avrea4 vCPUVM disk8,676, p99 35 µs, ×0.48
  5. GitHub4 vCPUnetwork disk · nobarrier4,366, p99 237 µs, ×0.24
  6. StarSling4 vCPUVM disk2,902, p99 29 µs, ×0.16
  7. Warpbuild4 vCPUVM disk1,987, p99 118 µs, ×0.11
  8. Ubicloud4 vCPUstandard · VM disk1,533, p99 3,621 µs, ×0.08
  9. AWS CodeBuild4 vCPUmedium · EBS563, p99 971 µs, ×0.03
  10. RunsOn4 vCPUm8azn.xlarge · EBS gp3 · nobarrier541, p99 963 µs, ×0.03

Namespace and Blacksmith lead x64 4 vCPU synced writes, within 5% (18,087 and 17,872).volatile and nobarrier mounts make each flush cheaper by making it less durable.

QD1 random readx64 at 8 vCPU · 4k, one request in flight · IOPS, higher is better
  1. Namespace8 vCPU8x32 · VM disk78,677, p99 12 µs, ×1.00
  2. Blacksmith8 vCPUVM disk75,819, p99 13 µs, ×0.96
  3. StarSling8 vCPUVM disk56,745, p99 17 µs, ×0.72
  4. Avrea8 vCPUVM disk42,785, p99 16 µs, ×0.54
  5. Warpbuild8 vCPUVM disk27,503, p99 48 µs, ×0.35
  6. RunsOn8 vCPUi7i.2xlarge · local NVMe11,030, p99 313 µs, ×0.14
  7. Ubicloud8 vCPUpremium · VM disk10,785, p99 167 µs, ×0.14
  8. GitHub8 vCPUVM disk7,942, p99 202 µs, ×0.10
  9. RunsOn8 vCPUm8a.2xlarge · EBS gp31,814, p99 905 µs, ×0.02
  10. AWS CodeBuild8 vCPUlarge · EBS1,754, p99 733 µs, ×0.02

Namespace and Blacksmith lead x64 8 vCPU QD1 read, within 5% (78,677 and 75,819).tmpfs for scale: 1,153,230 on RunsOn m8a.2xlarge · tmpfs.

Synced writesx64 at 8 vCPU · 4k + fdatasync · IOPS, higher is better
  1. Namespace8 vCPU8x32 · VM disk18,198, p99 20 µs, ×1.00
  2. Blacksmith8 vCPUVM disk · nobarrier18,157, p99 21 µs, ×1.00
  3. RunsOn8 vCPUi7i.2xlarge · local NVMe11,637, p99 38 µs, ×0.64
  4. Avrea8 vCPUVM disk7,570, p99 44 µs, ×0.42
  5. GitHub8 vCPUVM disk · nobarrier4,220, p99 232 µs, ×0.23
  6. StarSling8 vCPUVM disk3,260, p99 29 µs, ×0.18
  7. Ubicloud8 vCPUpremium · VM disk2,661, p99 1,172 µs, ×0.15
  8. Warpbuild8 vCPUVM disk2,133, p99 109 µs, ×0.12
  9. AWS CodeBuild8 vCPUlarge · EBS562, p99 987 µs, ×0.03
  10. RunsOn8 vCPUm8a.2xlarge · gp3 1000 MiB/s · nobarrier540, p99 1,012 µs, ×0.03

Namespace and Blacksmith lead x64 8 vCPU synced writes, within 5% (18,198 and 18,157).volatile and nobarrier mounts make each flush cheaper by making it less durable.

QD1 random readarm64 · 4k, one request in flight · IOPS, higher is better
  1. Warpbuild6 vCPUxfast (Apple M4 Pro) · VM disk26,620, p99 79 µs, ×1.00
  2. Blacksmith8 vCPUVM disk25,841, p99 33 µs, ×0.97
  3. Avrea4 vCPUVM disk21,376, p99 57 µs, ×0.80
  4. Namespace4 vCPUApple silicon 4x16 · VM disk19,715, p99 85 µs, ×0.74
  5. RunsOn8 vCPUm9gd.2xlarge · local NVMe13,514, p99 81 µs, ×0.51
  6. Ubicloud8 vCPUstandard · VM disk9,278, p99 379 µs, ×0.35
  7. GitHub4 vCPUnetwork disk8,202, p99 206 µs, ×0.31
  8. RunsOn4 vCPUc8g.xlarge · EBS gp31,838, p99 913 µs, ×0.07
  9. Warpbuild4 vCPUEBS1,816, p99 823 µs, ×0.07

Warpbuild and Blacksmith lead arm64 QD1 read, within 5% (26,620 and 25,841).tmpfs for scale: 700,578 on RunsOn m9g.xlarge · tmpfs.

Synced writesarm64 · 4k + fdatasync · IOPS, higher is better
  1. RunsOn8 vCPUm9gd.2xlarge · local NVMe17,511, p99 19 µs, ×1.00
  2. Warpbuild6 vCPUxfast (Apple M4 Pro) · VM disk · nobarrier8,770, p99 57 µs, ×0.50
  3. Blacksmith8 vCPUVM disk · nobarrier7,834, p99 57 µs, ×0.45
  4. GitHub4 vCPUnetwork disk · nobarrier4,381, p99 281 µs, ×0.25
  5. Avrea2 vCPUVM disk4,250, p99 55 µs, ×0.24
  6. Ubicloud2 vCPUstandard · VM disk4,147, p99 453 µs, ×0.24
  7. Namespace8 vCPU8x16 · VM disk4,071, p99 161 µs, ×0.23
  8. RunsOn8 vCPUm9g.2xlarge · EBS gp3 · nobarrier543, p99 995 µs, ×0.03
  9. Warpbuild8 vCPUEBS · nobarrier539, p99 979 µs, ×0.03

Fastest arm64 synced writes: RunsOn m9gd.2xlarge · NVMe (17,511), ahead of Warpbuild (8,770).volatile and nobarrier mounts make each flush cheaper by making it less durable.

QD1 random readarm64 at 2 vCPU · 4k, one request in flight · IOPS, higher is better
  1. Blacksmith2 vCPUVM disk21,992, p99 50 µs, ×1.00
  2. Avrea2 vCPUVM disk20,423, p99 58 µs, ×0.93
  3. Namespace2 vCPU2x8 · VM disk16,546, p99 92 µs, ×0.75
  4. RunsOn2 vCPUm9gd.large · local NVMe13,477, p99 81 µs, ×0.61
  5. Ubicloud2 vCPUstandard · VM disk8,741, p99 342 µs, ×0.40
  6. GitHub2 vCPUVM disk7,899, p99 232 µs, ×0.36
  7. Warpbuild2 vCPUEBS1,805, p99 823 µs, ×0.08
  8. RunsOn2 vCPUm9g.large · EBS gp31,788, p99 823 µs, ×0.08

Fastest arm64 2 vCPU QD1 read: Blacksmith (21,992), ahead of Avrea (20,423).tmpfs for scale: 700,578 on RunsOn m9g.xlarge · tmpfs.

Synced writesarm64 at 2 vCPU · 4k + fdatasync · IOPS, higher is better
  1. RunsOn2 vCPUm9gd.large · local NVMe7,267, p99 49 µs, ×1.00
  2. Blacksmith2 vCPUVM disk · nobarrier6,383, p99 95 µs, ×0.88
  3. Avrea2 vCPUVM disk4,250, p99 55 µs, ×0.58
  4. Ubicloud2 vCPUstandard · VM disk4,147, p99 453 µs, ×0.57
  5. Namespace2 vCPU2x8 · VM disk3,881, p99 189 µs, ×0.53
  6. GitHub2 vCPUVM disk · nobarrier3,094, p99 371 µs, ×0.43
  7. RunsOn2 vCPUm9g.large · EBS gp3 · nobarrier542, p99 987 µs, ×0.07
  8. Warpbuild2 vCPUEBS · nobarrier538, p99 995 µs, ×0.07

Fastest arm64 2 vCPU synced writes: RunsOn m9gd.large · NVMe (7,267), ahead of Blacksmith (6,383).volatile and nobarrier mounts make each flush cheaper by making it less durable.

QD1 random readarm64 at 4 vCPU · 4k, one request in flight · IOPS, higher is better
  1. Blacksmith4 vCPUVM disk23,747, p99 44 µs, ×1.00
  2. Avrea4 vCPUVM disk21,376, p99 57 µs, ×0.90
  3. Namespace4 vCPUApple silicon 4x16 · VM disk19,715, p99 85 µs, ×0.83
  4. RunsOn4 vCPUm9gd.xlarge · local NVMe13,439, p99 85 µs, ×0.57
  5. GitHub4 vCPUnetwork disk8,202, p99 206 µs, ×0.35
  6. Ubicloud4 vCPUstandard · VM disk7,432, p99 594 µs, ×0.31
  7. RunsOn4 vCPUc8g.xlarge · EBS gp31,838, p99 913 µs, ×0.08
  8. Warpbuild4 vCPUEBS1,816, p99 823 µs, ×0.08

Fastest arm64 4 vCPU QD1 read: Blacksmith (23,747), ahead of Avrea (21,376).tmpfs for scale: 700,578 on RunsOn m9g.xlarge · tmpfs.

Synced writesarm64 at 4 vCPU · 4k + fdatasync · IOPS, higher is better
  1. RunsOn4 vCPUm9gd.xlarge · local NVMe14,852, p99 23 µs, ×1.00
  2. Blacksmith4 vCPUVM disk · nobarrier7,280, p99 75 µs, ×0.49
  3. GitHub4 vCPUnetwork disk · nobarrier4,381, p99 281 µs, ×0.29
  4. Avrea4 vCPUVM disk3,920, p99 56 µs, ×0.26
  5. Namespace4 vCPU4x8 · VM disk3,761, p99 202 µs, ×0.25
  6. Ubicloud4 vCPUstandard · VM disk1,877, p99 3,424 µs, ×0.13
  7. RunsOn4 vCPUm9g.xlarge · EBS gp3 · nobarrier542, p99 987 µs, ×0.04
  8. Warpbuild4 vCPUEBS · nobarrier539, p99 979 µs, ×0.04

Fastest arm64 4 vCPU synced writes: RunsOn m9gd.xlarge · NVMe (14,852), ahead of Blacksmith (7,280).volatile and nobarrier mounts make each flush cheaper by making it less durable.

QD1 random readarm64 at 8 vCPU · 4k, one request in flight · IOPS, higher is better
  1. Blacksmith8 vCPUVM disk25,841, p99 33 µs, ×1.00
  2. Avrea8 vCPUVM disk20,543, p99 53 µs, ×0.79
  3. Namespace8 vCPU8x16 · VM disk16,363, p99 90 µs, ×0.63
  4. RunsOn8 vCPUm9gd.2xlarge · local NVMe13,514, p99 81 µs, ×0.52
  5. Ubicloud8 vCPUstandard · VM disk9,278, p99 379 µs, ×0.36
  6. RunsOn8 vCPUm9g.2xlarge · EBS gp31,810, p99 774 µs, ×0.07
  7. Warpbuild8 vCPUEBS1,808, p99 750 µs, ×0.07

Fastest arm64 8 vCPU QD1 read: Blacksmith (25,841), ahead of Avrea (20,543).tmpfs for scale: 700,578 on RunsOn m9g.xlarge · tmpfs.

Synced writesarm64 at 8 vCPU · 4k + fdatasync · IOPS, higher is better
  1. RunsOn8 vCPUm9gd.2xlarge · local NVMe17,511, p99 19 µs, ×1.00
  2. Blacksmith8 vCPUVM disk · nobarrier7,834, p99 57 µs, ×0.45
  3. Namespace8 vCPU8x16 · VM disk4,071, p99 161 µs, ×0.23
  4. Avrea8 vCPUVM disk3,834, p99 56 µs, ×0.22
  5. Ubicloud8 vCPUstandard · VM disk3,732, p99 979 µs, ×0.21
  6. RunsOn8 vCPUm9g.2xlarge · EBS gp3 · nobarrier543, p99 995 µs, ×0.03
  7. Warpbuild8 vCPUEBS · nobarrier539, p99 979 µs, ×0.03

Fastest arm64 8 vCPU synced writes: RunsOn m9gd.2xlarge · NVMe (17,511), ahead of Blacksmith (7,834).volatile and nobarrier mounts make each flush cheaper by making it less durable.

What the numbers say

Extremes on x64, and RAM against disk.

  • On x64, one small read at a time (4k, QD1) comes back 80,883 times a second on Blacksmith 2 vCPU and 1,520 on RunsOn m8a.xlarge · EBS gp3, 53× apart; p99 latency is 17 µs against 922 µs.
  • Synced 4k writes on x64 run from 498 per second on RunsOn m8i.2xlarge · EBS gp3 (workspace mounted nobarrier) to 18,654 on Blacksmith 2 vCPU (workspace mounted nobarrier).
  • r8a.large with tmpfs ($0.0010/min at spot) answers 1,089,234 QD1 reads and 423,214 synced writes per second: 90× and 32× the best local NVMe at 2 vCPU (i7i.large, $0.0010) and 601× and 782× default EBS gp3 (c8a.large, $0.0010); its workspace is 23 GiB, from RAM. (EC2 storage suite) What that does to real builds.
More findings23: EBS, arm64, NVMe vs EBS, provisioned gp3, tmpfs, storage classes
  • Every EBS-backed workspace (3 AWS CodeBuild x64 runners, 25 RunsOn configurations and 3 Warpbuild configurations) answers between 1,492 and 1,838 QD1 reads and 498 to 571 synced writes per second, whoever runs it and whatever throughput it is provisioned for: each request is a round trip to network storage.
  • On arm64, one small read at a time (4k, QD1) comes back 26,620 times a second on Warpbuild xfast (Apple M4 Pro) 6 vCPU and 1,492 on RunsOn c8g.large · EBS gp3, 18× apart; p99 latency is 79 µs against 954 µs.
  • Synced 4k writes on arm64 run from 537 per second on RunsOn c8g.large · EBS gp3 (workspace mounted nobarrier) to 17,511 on RunsOn m9gd.2xlarge · local NVMe.
  • Same Xeon 6975P-C CPU, different disk: m8id.2xlarge on local NVMe answers 10,517 QD1 reads and 7,522 synced writes per second, m8i.2xlarge on EBS gp3 1,571 and 498.
  • Same Xeon 6975P-C CPU, different disk: m8id.large on local NVMe answers 11,093 QD1 reads and 5,539 synced writes per second, m8i-flex.large on EBS gp3 1,745 and 532.
  • Same Xeon 6975P-C CPU, different disk: m8id.xlarge on local NVMe answers 11,046 QD1 reads and 7,973 synced writes per second, m8i-flex.xlarge on EBS gp3 1,707 and 520.
  • Same Neoverse-V3 CPU, different disk: m9gd.2xlarge on local NVMe answers 13,514 QD1 reads and 17,511 synced writes per second, m9g.2xlarge on EBS gp3 1,810 and 543.
  • Same Neoverse-V3 CPU, different disk: m9gd.xlarge on local NVMe answers 13,439 QD1 reads and 14,852 synced writes per second, m9g.xlarge on EBS gp3 1,560 and 542.
  • Same Neoverse-V3 CPU, different disk: m9gd.large on local NVMe answers 13,477 QD1 reads and 7,267 synced writes per second, m9g.large on EBS gp3 1,788 and 542.
  • Provisioning gp3 at 1000 MiB/s on m8a.2xlarge takes sequential reads from 402 MiB/s to 1,002 MiB/s (2.5×); QD1 reads barely move (1,791 → 1,792 IOPS): it buys bandwidth, not latency.
  • Provisioning gp3 at 1000 MiB/s on m8azn.xlarge takes sequential reads from 401 MiB/s to 1,001 MiB/s (2.5×); QD1 reads barely move (1,815 → 1,773 IOPS): it buys bandwidth, not latency.
  • tmpfs on m8a.2xlarge is not a disk at all: 1,153,230 QD1 reads and 427,176 synced writes per second, from RAM. The workspace is 46 GiB, sized by memory.
  • tmpfs on m9g.2xlarge is not a disk at all: 664,023 QD1 reads and 301,114 synced writes per second, from RAM. The workspace is 46 GiB, sized by memory.
  • tmpfs on m9g.xlarge is not a disk at all: 700,578 QD1 reads and 303,857 synced writes per second, from RAM. The workspace is 23 GiB, sized by memory.
  • tmpfs on r8a.2xlarge is not a disk at all: 1,151,439 QD1 reads and 428,713 synced writes per second, from RAM. The workspace is 92 GiB, sized by memory.
  • tmpfs on r8a.xlarge is not a disk at all: 1,083,980 QD1 reads and 431,907 synced writes per second, from RAM. The workspace is 46 GiB, sized by memory.
  • tmpfs on r9g.large is not a disk at all: 641,530 QD1 reads and 298,044 synced writes per second, from RAM. The workspace is 23 GiB, sized by memory.
  • tmpfs on r9g.xlarge is not a disk at all: 658,442 QD1 reads and 302,438 synced writes per second, from RAM. The workspace is 46 GiB, sized by memory.
  • tmpfs: 642k–1.2M QD1 reads and 298k–432k synced writes per second across 8 runners (8 RunsOn configurations).
  • VM disk: 6.4k–81k QD1 reads and 1.3k–19k synced writes per second across 43 runners from 7 providers (6 Avrea runners, 6 Blacksmith runners, 3 GitHub runners, 12 Namespace runners, 2 StarSling x64 runners, 9 Ubicloud runners and 5 Warpbuild runners).
  • local NVMe: 11k–14k QD1 reads and 5.5k–18k synced writes per second across 9 runners (9 RunsOn configurations).
  • network disk: 7.5k–8.2k QD1 reads and 4.4k synced writes per second across 2 runners (2 GitHub runners).
  • EBS: 1.5k–1.8k QD1 reads and 498–571 synced writes per second across 31 runners from 3 providers (3 AWS CodeBuild x64 runners, 25 RunsOn configurations and 3 Warpbuild configurations).

Reading these numbers

fio measures what a disk can do. Whether a job gets there depends on the job.

At 4 vCPU, Namespace 4x8 answers 51× the QD1 reads of RunsOn m8a.xlarge · EBS gp3 (78,187 against 1,520 per second), and the Rust build takes 1m 52s on one and 1m 48s on the other. Every build, per runner.

What each column says about a job

  • QD1 reads and synced writes: databases, SQLite-backed tests and anything that flushes each write. Every flush waits for the storage, and a network disk pays a round trip each time.
  • Random writes at depth and sequential throughput: docker build layers, package installs and cache archives. They batch their writes and run into the disk's ceiling, not its latency.
  • None of them: compile jobs. A compiler waits for the CPU, and it reads its files back from the page cache.

Every runner

Each provider's best disk first; its other machines sit behind +N more. Bars are log scale.

One request at a time 4k, 32 in flight Sequential, 1M
Runner QD1 read ↑p99 ↓Sync write ↑Read ↑Write ↑Read ↑Write ↑
x6457 runners, 9 providers
Blacksmith 2 vCPU 8 GB VM disk EPYC · model hidden nobarrier 80,883 17 µs 18,654 795,024 190,497 7.3 GiB/s 2.1 GiB/s
8 vCPU 8 vCPU 32 GB VM disk EPYC · model hidden nobarrier 75,819 13 µs 18,157 571,040 337,040 6.5 GiB/s 2.1 GiB/s
4 vCPU 4 vCPU 16 GB VM disk EPYC · model hidden nobarrier 71,607 14 µs 17,872 769,525 239,556 6.5 GiB/s 2.0 GiB/s
Namespace 8x32 8 vCPU 32 GB VM disk EPYC · model hidden 78,677 12 µs 18,198 1,106,358 522,909 4.1 GiB/s 2.9 GiB/s
8x16 8 vCPU 16 GB VM disk EPYC · model hidden 76,839 13 µs 17,698 1,109,002 476,969 4.1 GiB/s 2.9 GiB/s
4x16 4 vCPU 16 GB VM disk EPYC · model hidden 77,169 13 µs 17,693 988,446 406,763 4.1 GiB/s 2.9 GiB/s
4x8 4 vCPU 8 GB VM disk EPYC · model hidden 78,187 13 µs 18,087 1,000,575 429,133 4.1 GiB/s 2.9 GiB/s
2x8 2 vCPU 8 GB VM disk EPYC · model hidden 77,442 13 µs 17,813 351,895 227,732 4.1 GiB/s 2.9 GiB/s
StarSling 8 vCPU 32 GB VM disk EPYC · model hidden 56,745 17 µs 3,260 231,481 40,717 2.4 GiB/s 2.7 GiB/s
4 vCPU 4 vCPU 16 GB VM disk EPYC · model hidden 55,952 18 µs 2,902 243,587 47,132 3.9 GiB/s 3.3 GiB/s
Avrea 2 vCPU 8 GB VM disk EPYC 4585PX 44,589 17 µs 8,416 366,117 317,490 12.0 GiB/s 7.5 GiB/s
8 vCPU 8 vCPU 32 GB VM disk EPYC 4585PX 42,785 16 µs 7,570 343,640 217,415 6.6 GiB/s 6.8 GiB/s
4 vCPU 4 vCPU 16 GB VM disk EPYC 4585PX 43,283 20 µs 8,676 468,080 224,464 8.6 GiB/s 5.6 GiB/s
Warpbuild 8 vCPU 32 GB VM disk Ryzen 9 9950X 27,503 48 µs 2,133 154,260 45,671 8.4 GiB/s 5.1 GiB/s
4 vCPU 4 vCPU 16 GB VM disk Ryzen 9 9950X 21,207 58 µs 1,987 185,061 38,883 9.1 GiB/s 5.4 GiB/s
2 vCPU 2 vCPU 8 GB VM disk Ryzen 9 9950X 24,646 59 µs 2,084 152,215 53,614 6.7 GiB/s 4.5 GiB/s
RunsOn i7i.xlarge 4 vCPU 32 GB local NVMe Xeon 8559C 11,437 301 µs 12,559 150,052 82,489 1,010 MiB/s 788 MiB/s
m8azn.3xlarge 12 vCPU 48 GB EBS gp3 EPYC 9R05 nobarrier 1,641 995 µs 540 2,997 2,994 401 MiB/s 401 MiB/s
m8a.2xlarge 8 vCPU 32 GB EBS gp3 EPYC 9R45 nobarrier 1,814 905 µs 539 2,994 2,994 401 MiB/s 401 MiB/s
m8a.2xlarge 8 vCPU 32 GB gp3 1000 MiB/s EPYC 9R45 nobarrier 1,579 946 µs 540 15,996 15,992 1,001 MiB/s 1,001 MiB/s
c8a.2xlarge 8 vCPU 16 GB EBS gp3 EPYC 9R45 nobarrier 1,549 856 µs 540 2,995 2,992 401 MiB/s 401 MiB/s
r8a.2xlarge 8 vCPU 64 GB tmpfs EPYC 9R45 1,151,439 <1 µs 428,713 4,271,309 3,819,444 18.5 GiB/s 10.0 GiB/s
m8a.2xlarge 8 vCPU 32 GB tmpfs EPYC 9R45 1,153,230 <1 µs 427,176 4,255,814 3,787,945 18.1 GiB/s 9.9 GiB/s
m8azn.xlarge 4 vCPU 16 GB EBS gp3 EPYC 9R05 nobarrier 1,815 848 µs 541 2,994 2,991 401 MiB/s 401 MiB/s
m8azn.xlarge 4 vCPU 16 GB gp3 1000 MiB/s EPYC 9R05 nobarrier 1,773 823 µs 541 15,994 15,992 1,001 MiB/s 1,001 MiB/s
m8id.2xlarge 8 vCPU 32 GB local NVMe Xeon 6975P-C 10,517 272 µs 7,522 134,258 67,071 905 MiB/s 432 MiB/s
m8i.2xlarge 8 vCPU 32 GB EBS gp3 Xeon 6975P-C nobarrier 1,571 913 µs 498 2,994 2,993 401 MiB/s 401 MiB/s
m8i-flex.2xlarge 8 vCPU 32 GB EBS gp3 Xeon 6975P-C nobarrier 1,754 922 µs 519 2,993 2,994 401 MiB/s 401 MiB/s
i7i.2xlarge 8 vCPU 64 GB local NVMe Xeon 8559C 11,030 313 µs 11,637 300,465 165,111 2.0 GiB/s 1.5 GiB/s
m8a.xlarge 4 vCPU 16 GB EBS gp3 EPYC 9R45 nobarrier 1,520 922 µs 540 2,994 2,991 401 MiB/s 401 MiB/s
r8a.xlarge 4 vCPU 32 GB tmpfs EPYC 9R45 1,083,980 <1 µs 431,907 4,122,257 3,786,762 18.4 GiB/s 9.9 GiB/s
c8a.xlarge 4 vCPU 8 GB EBS gp3 EPYC 9R45 nobarrier 1,790 832 µs 541 2,994 2,992 401 MiB/s 401 MiB/s
m8azn.large 2 vCPU 8 GB EBS gp3 EPYC 9R05 nobarrier 1,795 815 µs 542 2,994 2,992 401 MiB/s 401 MiB/s
m8id.xlarge 4 vCPU 16 GB local NVMe Xeon 6975P-C 11,046 206 µs 7,973 67,090 33,524 451 MiB/s 216 MiB/s
m8i-flex.xlarge 4 vCPU 16 GB EBS gp3 Xeon 6975P-C nobarrier 1,707 848 µs 520 2,994 2,992 401 MiB/s 401 MiB/s
m8i.xlarge 4 vCPU 16 GB EBS gp3 Xeon 6975P-C nobarrier 1,676 832 µs 523 2,992 2,994 401 MiB/s 401 MiB/s
m8a.large 2 vCPU 8 GB EBS gp3 EPYC 9R45 nobarrier 1,782 774 µs 541 2,994 2,992 401 MiB/s 401 MiB/s
r8a.large 2 vCPU 16 GB EBS gp3 EPYC 9R45 nobarrier 1,780 766 µs 541 2,994 2,992 401 MiB/s 401 MiB/s
r8a.large 2 vCPU 16 GB tmpfs EPYC 9R45 1,089,234 <1 µs 423,214 2,164,544 1,939,598 18.3 GiB/s 9.8 GiB/s
c8a.large 2 vCPU 4 GB EBS gp3 EPYC 9R45 nobarrier 1,812 741 µs 541 2,994 2,992 401 MiB/s 401 MiB/s
m8id.large 2 vCPU 8 GB local NVMe Xeon 6975P-C 11,093 216 µs 5,539 33,542 16,754 226 MiB/s 108 MiB/s
i7i.large 2 vCPU 16 GB local NVMe Xeon 8559C 11,384 313 µs 13,194 75,023 41,229 503 MiB/s 395 MiB/s
m8i-flex.large 2 vCPU 8 GB EBS gp3 Xeon 6975P-C nobarrier 1,745 848 µs 532 2,994 2,992 401 MiB/s 401 MiB/s
m8i.large 2 vCPU 8 GB EBS gp3 Xeon 6975P-C nobarrier 1,703 881 µs 535 2,993 2,994 401 MiB/s 401 MiB/s
t8i.medium 2 vCPU 4 GB EBS gp3 Xeon 6975P-C nobarrier 1,786 823 µs 523 3,016 2,998 401 MiB/s 401 MiB/s
Ubicloud premium 8 vCPU 32 GB VM disk Ryzen 9 7950X3D 10,785 167 µs 2,661 366,118 22,032 3.5 GiB/s 1.4 GiB/s
standard 8 vCPU 8 vCPU 32 GB VM disk EPYC 9454P 8,031 528 µs 1,423 251,230 13,012 2.7 GiB/s 752 MiB/s
premium 4 vCPU 4 vCPU 16 GB VM disk Ryzen 9 7950X3D 6,461 2,073 µs 1,254 143,006 8,602 2.4 GiB/s 537 MiB/s
standard 4 vCPU 4 vCPU 16 GB VM disk EPYC 9454 9,145 465 µs 1,533 193,790 12,781 2.5 GiB/s 668 MiB/s
standard 2 vCPU 2 vCPU 8 GB VM disk EPYC 9454P 6,445 1,106 µs 1,446 105,928 60,814 2.6 GiB/s 622 MiB/s
premium 2 vCPU 2 vCPU 8 GB VM disk Ryzen 9 7950X3D 6,564 1,597 µs 2,683 129,551 69,948 2.6 GiB/s 764 MiB/s
GitHub 8 vCPU 32 GB VM disk EPYC 9V74 nobarrier 7,942 202 µs 4,220 38,946 18,507 783 MiB/s 532 MiB/s
4-core 4 vCPU 16 GB network disk Xeon 8370C nobarrier 7,479 210 µs 4,366 19,578 9,322 394 MiB/s 247 MiB/s
2-core 2 vCPU 8 GB VM disk EPYC 9V45 nobarrier 7,544 222 µs 4,559 9,383 8,788 199 MiB/s 130 MiB/s
AWS CodeBuild medium 4 vCPU 8 GB EBS Xeon 8488C 1,766 717 µs 563 2,990 2,979 251 MiB/s 251 MiB/s
large 8 vCPU 16 GB EBS Xeon 8488C 1,754 733 µs 562 2,993 2,977 251 MiB/s 251 MiB/s
small 2 vCPU 3 GB EBS Xeon 8488C 1,760 774 µs 571 2,990 2,972 195 MiB/s 251 MiB/s
arm6436 runners, 7 providers
Warpbuild xfast (Apple M4 Pro) 6 vCPU 14 GB VM disk nobarrier 26,620 79 µs 8,770 321,484 5,369 19.4 GiB/s 25.4 GiB/s
xfast (Apple M4 Pro) 12 vCPU 12 vCPU 28 GB VM disk nobarrier 23,397 52 µs 8,309 329,647 4,460 21.6 GiB/s 25.1 GiB/s
8 vCPU 8 vCPU 32 GB EBS Neoverse-V2 nobarrier 1,808 750 µs 539 4,995 4,993 401 MiB/s 401 MiB/s
4 vCPU 4 vCPU 16 GB EBS Neoverse-V2 nobarrier 1,816 823 µs 539 4,193 4,193 302 MiB/s 302 MiB/s
2 vCPU 2 vCPU 8 GB EBS Neoverse-V2 nobarrier 1,805 823 µs 538 4,194 4,193 302 MiB/s 301 MiB/s
Blacksmith 8 vCPU 32 GB VM disk Ampere-1a nobarrier 25,841 33 µs 7,834 259,773 29,073 1.6 GiB/s 993 MiB/s
4 vCPU 4 vCPU 16 GB VM disk Ampere-1a nobarrier 23,747 44 µs 7,280 171,567 27,356 1.6 GiB/s 863 MiB/s
2 vCPU 2 vCPU 6 GB VM disk Ampere-1a nobarrier 21,992 50 µs 6,383 74,915 26,068 1.7 GiB/s 823 MiB/s
Avrea 4 vCPU 16 GB VM disk Apple M5 Max · as stated by the provider 21,376 57 µs 3,920 147,493 67,748 31.5 GiB/s 17.1 GiB/s
8 vCPU 8 vCPU 32 GB VM disk Apple M5 Max · as stated by the provider 20,543 53 µs 3,834 139,939 17,597 43.1 GiB/s 16.1 GiB/s
2 vCPU 2 vCPU 8 GB VM disk Apple M5 Max · as stated by the provider 20,423 58 µs 4,250 167,165 14,993 30.4 GiB/s 14.8 GiB/s
Namespace Apple silicon 4x16 4 vCPU 16 GB VM disk CPU not reported 19,715 85 µs 3,461 148,271 13,347 31.2 GiB/s 14.7 GiB/s
Apple silicon 2x8 2 vCPU 8 GB VM disk CPU not reported 18,861 90 µs 3,744 155,899 22,462 32.7 GiB/s 12.4 GiB/s
8x32 8 vCPU 32 GB VM disk Ampere-1a 15,699 98 µs 3,933 180,257 39,396 942 MiB/s 756 MiB/s
8x16 8 vCPU 16 GB VM disk Ampere-1a 16,363 90 µs 4,071 171,247 45,165 901 MiB/s 746 MiB/s
4x8 4 vCPU 8 GB VM disk Ampere-1a 17,003 87 µs 3,761 144,201 32,144 962 MiB/s 739 MiB/s
4x16 4 vCPU 16 GB VM disk Ampere-1a 16,649 88 µs 3,758 141,434 32,179 962 MiB/s 750 MiB/s
2x8 2 vCPU 8 GB VM disk Ampere-1a 16,546 92 µs 3,881 79,835 28,646 941 MiB/s 696 MiB/s
RunsOn m9gd.2xlarge 8 vCPU 32 GB local NVMe Neoverse-V3 13,514 81 µs 17,511 174,572 87,209 1.1 GiB/s 561 MiB/s
m9g.2xlarge 8 vCPU 32 GB EBS gp3 Neoverse-V3 nobarrier 1,810 774 µs 543 2,995 2,992 401 MiB/s 401 MiB/s
m9g.2xlarge 8 vCPU 32 GB tmpfs Neoverse-V3 664,023 <1 µs 301,114 2,693,202 2,518,860 14.1 GiB/s 9.9 GiB/s
c8g.2xlarge 8 vCPU 16 GB EBS gp3 Neoverse-V2 nobarrier 1,778 848 µs 539 2,994 2,992 401 MiB/s 401 MiB/s
m9gd.xlarge 4 vCPU 16 GB local NVMe Neoverse-V3 13,439 85 µs 14,852 87,221 43,593 585 MiB/s 281 MiB/s
m9g.xlarge 4 vCPU 16 GB EBS gp3 Neoverse-V3 nobarrier 1,560 938 µs 542 2,994 2,992 401 MiB/s 401 MiB/s
m9g.xlarge 4 vCPU 16 GB tmpfs Neoverse-V3 700,578 <1 µs 303,857 2,759,837 2,553,373 15.9 GiB/s 10.1 GiB/s
r9g.xlarge 4 vCPU 32 GB tmpfs Neoverse-V3 658,442 <1 µs 302,438 2,646,436 2,497,143 13.9 GiB/s 9.2 GiB/s
c8g.xlarge 4 vCPU 8 GB EBS gp3 Neoverse-V2 nobarrier 1,838 913 µs 538 2,994 2,992 401 MiB/s 401 MiB/s
m9gd.large 2 vCPU 8 GB local NVMe Neoverse-V3 13,477 81 µs 7,267 43,607 21,783 293 MiB/s 141 MiB/s
m9g.large 2 vCPU 8 GB EBS gp3 Neoverse-V3 nobarrier 1,788 823 µs 542 2,993 2,994 401 MiB/s 401 MiB/s
r9g.large 2 vCPU 16 GB tmpfs Neoverse-V3 641,530 <1 µs 298,044 1,252,121 1,219,266 13.3 GiB/s 8.9 GiB/s
c8g.large 2 vCPU 4 GB EBS gp3 Neoverse-V2 nobarrier 1,492 954 µs 537 2,992 2,994 401 MiB/s 401 MiB/s
Ubicloud standard 8 vCPU 32 GB VM disk Neoverse-N1 9,278 379 µs 3,732 223,613 119,660 886 MiB/s 487 MiB/s
standard 4 vCPU 4 vCPU 16 GB VM disk Neoverse-N1 7,432 594 µs 1,877 173,246 46,361 810 MiB/s 392 MiB/s
standard 2 vCPU 2 vCPU 8 GB VM disk Neoverse-N1 8,741 342 µs 4,147 93,715 33,743 892 MiB/s 481 MiB/s
GitHub 4 vCPU 16 GB network disk Neoverse-N2 nobarrier 8,202 206 µs 4,381 19,606 11,809 394 MiB/s 339 MiB/s
2-core 2 vCPU 8 GB VM disk Neoverse-N2 nobarrier 7,899 232 µs 3,094 9,376 6,017 199 MiB/s 164 MiB/s
  • IOPS are 4k blocks, medians of finished jobs
  • bold best disk measured on the arch (tmpfs is RAM, left out)
  • volatile, nobarrier: cheaper, less durable flushes

Pick the disk per job on RunsOn

How it's measured

Methodology

fio runs inside the job, in GITHUB_WORKSPACE: the disk a build writes to, on the filesystem the provider mounted there. Every runner is compared, whatever its shape.

fio settingsblock sizes, queue depths, mounts
  • QD1 random read: 4k blocks, one request in flight; IOPS and p99 latency.
  • Sync write: 4k writes, each followed by fdatasync.
  • Random read and write: 4k blocks, 4 jobs with 32 requests in flight each.
  • Sequential read and write: 1M blocks, 32 requests in flight.
  • The workspace filesystem, its size and its mount options come from the job's own mount table.
  • Earlier versions of this page used a different harness and other fio settings on 2 vCPU runners; those numbers are gone rather than mixed in.