self-host →

Fastest GitHub Actions runners: disk I/O.

fio inside the job workspace of 89 runners from 9 providers, 2 to 12 vCPU. Latency first: a build waits on small reads and synced writes far more often than it streams one big file.

Fastest QD1 read, x64 84,854 Blacksmith 4 vCPU · reads/s
Fastest QD1 read, arm64 26,844 Warpbuild xfast (Apple M4 Pro) 6 vCPU · reads/s
GitHub's fastest runner 7,942 x64 QD1 reads/s on GitHub 8-core
Fastest synced writes, x64 20,425 Blacksmith 4 vCPU · writes/s · nobarrier mount
tmpfs, for scale 1.2M QD1 reads/s on RunsOn m8a.2xlarge · tmpfs: RAM, not a disk, never ranked

Latency per provider

Each provider's best disk. QD1 is one 4k read at a time, the way a build reads thousands of small files. 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. Blacksmith4 vCPUVM disk84,854, p99 14 µs, ×1.00
  2. Namespace8 vCPU8x32 · VM disk78,586, p99 13 µs, ×0.93
  3. StarSling8 vCPUVM disk56,745, p99 17 µs, ×0.67
  4. Avrea4 vCPUVM disk47,519, p99 18 µs, ×0.56
  5. Warpbuild2 vCPUVM disk24,646, p99 59 µs, ×0.29
  6. RunsOn8 vCPUi7i.2xlarge · local NVMe12,709, p99 228 µs, ×0.15
  7. Ubicloud8 vCPUpremium · VM disk10,677, p99 305 µs, ×0.13
  8. GitHub8 vCPUVM disk7,942, p99 232 µs, ×0.09
  9. AWS CodeBuild4 vCPUmedium · EBS1,756, p99 758 µs, ×0.02

tmpfs for scale: 1,156,332 on RunsOn m8a.2xlarge · tmpfs.

Synced writesx64 · 4k + fdatasync · IOPS, higher is better
  1. Blacksmith4 vCPUVM disk · nobarrier20,425, p99 22 µs, ×1.00
  2. Namespace8 vCPU8x32 · VM disk18,160, p99 21 µs, ×0.89
  3. RunsOn2 vCPUi7i.large · local NVMe13,514, p99 31 µs, ×0.66
  4. Avrea4 vCPUVM disk8,648, p99 38 µs, ×0.42
  5. GitHub2 vCPUVM disk · nobarrier4,336, p99 212 µs, ×0.21
  6. Ubicloud8 vCPUpremium · VM disk4,203, p99 338 µs, ×0.21
  7. StarSling4 vCPUVM disk · volatile3,385, p99 28 µs, ×0.17
  8. Warpbuild2 vCPUVM disk2,056, p99 119 µs, ×0.10
  9. AWS CodeBuild2 vCPUsmall · EBS562, p99 995 µs, ×0.03

volatile and nobarrier mounts make each flush cheaper by making it less durable.

QD1 random readx64 · 4k, one request in flight · IOPS, higher is better
  1. RunsOn8 vCPUm8a.2xlarge · tmpfs · RAM1,156,332, p99 <1 µs, ×14
  2. RunsOn8 vCPUr8a.2xlarge · tmpfs · RAM1,154,342, p99 <1 µs, ×14
  3. RunsOn4 vCPUr8a.xlarge · tmpfs · RAM1,071,527, p99 <1 µs, ×13
  4. Blacksmith4 vCPUVM disk84,854, p99 14 µs, ×1.00
  5. Namespace8 vCPU8x32 · VM disk78,586, p99 13 µs, ×0.93
  6. StarSling8 vCPUVM disk56,745, p99 17 µs, ×0.67
  7. Avrea4 vCPUVM disk47,519, p99 18 µs, ×0.56
  8. Warpbuild2 vCPUVM disk24,646, p99 59 µs, ×0.29
  9. RunsOn8 vCPUi7i.2xlarge · local NVMe12,709, p99 228 µs, ×0.15
  10. Ubicloud8 vCPUpremium · VM disk10,677, p99 305 µs, ×0.13
  11. GitHub8 vCPUVM disk7,942, p99 232 µs, ×0.09
  12. AWS CodeBuild4 vCPUmedium · EBS1,756, p99 758 µs, ×0.02

Hatched: tmpfs, the workspace in RAM. Multipliers are against the best disk.

Synced writesx64 · 4k + fdatasync · IOPS, higher is better
  1. RunsOn8 vCPUr8a.2xlarge · tmpfs · RAM433,632, p99 <1 µs, ×21
  2. RunsOn8 vCPUm8a.2xlarge · tmpfs · RAM432,491, p99 <1 µs, ×21
  3. RunsOn4 vCPUr8a.xlarge · tmpfs · RAM431,794, p99 <1 µs, ×21
  4. Blacksmith4 vCPUVM disk · nobarrier20,425, p99 22 µs, ×1.00
  5. Namespace8 vCPU8x32 · VM disk18,160, p99 21 µs, ×0.89
  6. RunsOn2 vCPUi7i.large · local NVMe13,514, p99 31 µs, ×0.66
  7. Avrea4 vCPUVM disk8,648, p99 38 µs, ×0.42
  8. GitHub2 vCPUVM disk · nobarrier4,336, p99 212 µs, ×0.21
  9. Ubicloud8 vCPUpremium · VM disk4,203, p99 338 µs, ×0.21
  10. StarSling4 vCPUVM disk · volatile3,385, p99 28 µs, ×0.17
  11. Warpbuild2 vCPUVM disk2,056, p99 119 µs, ×0.10
  12. AWS CodeBuild2 vCPUsmall · EBS562, p99 995 µs, ×0.03

Hatched: tmpfs, the workspace in RAM. Multipliers are against the best disk.

QD1 random readarm64 · 4k, one request in flight · IOPS, higher is better
  1. Warpbuild6 vCPUxfast (Apple M4 Pro) · VM disk26,844, p99 41 µs, ×1.00
  2. Blacksmith8 vCPUVM disk25,841, p99 34 µs, ×0.96
  3. Avrea8 vCPUVM disk18,850, p99 53 µs, ×0.70
  4. Namespace4 vCPUApple silicon · VM disk18,455, p99 85 µs, ×0.69
  5. RunsOn2 vCPUm9gd.large · local NVMe13,492, p99 81 µs, ×0.50
  6. Ubicloud2 vCPUstandard · VM disk9,482, p99 334 µs, ×0.35
  7. GitHub4 vCPUnetwork disk8,635, p99 202 µs, ×0.32

tmpfs for scale: 682,673 on RunsOn m9g.xlarge · tmpfs.

Synced writesarm64 · 4k + fdatasync · IOPS, higher is better
  1. RunsOn8 vCPUm9gd.2xlarge · local NVMe17,318, p99 20 µs, ×1.00
  2. Warpbuild6 vCPUxfast (Apple M4 Pro) · VM disk · nobarrier8,765, p99 53 µs, ×0.51
  3. Blacksmith8 vCPUVM disk · nobarrier7,676, p99 58 µs, ×0.44
  4. GitHub4 vCPUnetwork disk · nobarrier4,419, p99 259 µs, ×0.26
  5. Ubicloud2 vCPUstandard · VM disk4,342, p99 412 µs, ×0.25
  6. Avrea2 vCPUVM disk4,222, p99 55 µs, ×0.24
  7. Namespace8 vCPU8x32 · VM disk3,974, p99 169 µs, ×0.23

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. RunsOn4 vCPUm9g.xlarge · tmpfs · RAM682,673, p99 <1 µs, ×25
  2. RunsOn8 vCPUm9g.2xlarge · tmpfs · RAM653,143, p99 <1 µs, ×24
  3. Warpbuild6 vCPUxfast (Apple M4 Pro) · VM disk26,844, p99 41 µs, ×1.00
  4. Blacksmith8 vCPUVM disk25,841, p99 34 µs, ×0.96
  5. Avrea8 vCPUVM disk18,850, p99 53 µs, ×0.70
  6. Namespace4 vCPUApple silicon · VM disk18,455, p99 85 µs, ×0.69
  7. RunsOn2 vCPUm9gd.large · local NVMe13,492, p99 81 µs, ×0.50
  8. Ubicloud2 vCPUstandard · VM disk9,482, p99 334 µs, ×0.35
  9. GitHub4 vCPUnetwork disk8,635, p99 202 µs, ×0.32

Hatched: tmpfs, the workspace in RAM. Multipliers are against the best disk.

Synced writesarm64 · 4k + fdatasync · IOPS, higher is better
  1. RunsOn4 vCPUm9g.xlarge · tmpfs · RAM303,857, p99 <1 µs, ×18
  2. RunsOn8 vCPUm9g.2xlarge · tmpfs · RAM301,438, p99 <1 µs, ×17
  3. RunsOn8 vCPUm9gd.2xlarge · local NVMe17,318, p99 20 µs, ×1.00
  4. Warpbuild6 vCPUxfast (Apple M4 Pro) · VM disk · nobarrier8,765, p99 53 µs, ×0.51
  5. Blacksmith8 vCPUVM disk · nobarrier7,676, p99 58 µs, ×0.44
  6. GitHub4 vCPUnetwork disk · nobarrier4,419, p99 259 µs, ×0.26
  7. Ubicloud2 vCPUstandard · VM disk4,342, p99 412 µs, ×0.25
  8. Avrea2 vCPUVM disk4,222, p99 55 µs, ×0.24
  9. Namespace8 vCPU8x32 · VM disk3,974, p99 169 µs, ×0.23

Hatched: tmpfs, the workspace in RAM. Multipliers are against the best disk.

What the numbers say

Extremes on x64, and RAM against disk.

  • On x64, one small read at a time (4k, QD1) comes back 84,854 times a second on Blacksmith 4 vCPU and 1,569 on RunsOn m8i.2xlarge · EBS gp3, 54× apart; p99 latency is 14 µs against 1,012 µs.
  • Synced 4k writes on x64 run from 498 per second on RunsOn m8i.2xlarge · EBS gp3 (workspace mounted nobarrier) to 20,425 on Blacksmith 4 vCPU (workspace mounted nobarrier).
  • r8a.xlarge with tmpfs ($0.0021/min at spot) answers 1,071,527 QD1 reads and 431,794 synced writes per second: 88× and 36× the best local NVMe at 4 vCPU (i7i.xlarge, $0.0019) and 584× and 800× default EBS gp3 (m8a.xlarge, $0.0015); its workspace is 31 GiB, from RAM. (EC2 storage suite)
More findings20: 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,568 and 1,844 QD1 reads and 498 to 562 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,844 times a second on Warpbuild xfast (Apple M4 Pro) 6 vCPU and 1,568 on RunsOn m9g.xlarge · EBS gp3, 17× apart; p99 latency is 41 µs against 946 µs.
  • Synced 4k writes on arm64 run from 537 per second on RunsOn c8g.large · EBS gp3 (workspace mounted nobarrier) to 17,318 on RunsOn m9gd.2xlarge · local NVMe.
  • Same Xeon 6975P-C CPU, different disk: m8id.2xlarge on local NVMe answers 10,957 QD1 reads and 7,657 synced writes per second, m8i.2xlarge on EBS gp3 1,569 and 498.
  • Same Xeon 6975P-C CPU, different disk: m8id.large on local NVMe answers 10,991 QD1 reads and 5,549 synced writes per second, m8i-flex.large on EBS gp3 1,745 and 530.
  • Same Xeon 6975P-C CPU, different disk: m8id.xlarge on local NVMe answers 11,045 QD1 reads and 7,898 synced writes per second, m8i-flex.xlarge on EBS gp3 1,765 and 527.
  • Same Neoverse-V3 CPU, different disk: m9gd.2xlarge on local NVMe answers 13,464 QD1 reads and 17,318 synced writes per second, m9g.2xlarge on EBS gp3 1,788 and 543.
  • Same Neoverse-V3 CPU, different disk: m9gd.xlarge on local NVMe answers 12,704 QD1 reads and 12,664 synced writes per second, m9g.xlarge on EBS gp3 1,568 and 543.
  • Same Neoverse-V3 CPU, different disk: m9gd.large on local NVMe answers 13,492 QD1 reads and 7,267 synced writes per second, m9g.large on EBS gp3 1,621 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,773 → 1,764 IOPS): it buys bandwidth, not latency.
  • tmpfs on m8a.2xlarge is not a disk at all: 1,156,332 QD1 reads and 432,491 synced writes per second, from RAM. The workspace is 31 GiB, sized by memory.
  • tmpfs on m9g.2xlarge is not a disk at all: 653,143 QD1 reads and 301,438 synced writes per second, from RAM. The workspace is 31 GiB, sized by memory.
  • tmpfs on m9g.xlarge is not a disk at all: 682,673 QD1 reads and 303,857 synced writes per second, from RAM. The workspace is 15 GiB, sized by memory.
  • tmpfs on r8a.2xlarge is not a disk at all: 1,154,342 QD1 reads and 433,632 synced writes per second, from RAM. The workspace is 62 GiB, sized by memory.
  • tmpfs: 653k–1.2M QD1 reads and 301k–434k synced writes per second across 5 runners (5 RunsOn configurations).
  • VM disk: 6.0k–85k QD1 reads and 578–20k synced writes per second across 42 runners from 7 providers (6 Avrea runners, 6 Blacksmith runners, 3 GitHub runners, 11 Namespace runners, 2 StarSling x64 runners, 9 Ubicloud runners and 5 Warpbuild runners).
  • local NVMe: 11k–13k QD1 reads and 5.5k–17k synced writes per second across 9 runners (9 RunsOn configurations).
  • network disk: 6.7k–8.6k QD1 reads and 3.1k–4.4k synced writes per second across 2 runners (2 GitHub runners).
  • EBS: 1.6k–1.8k QD1 reads and 498–562 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

Most of a build is small, dependent I/O, not one big stream.

Why latency before throughput

  • git checkout, npm install, cargo build and test runners read thousands of small files, each waiting for the last: the QD1 column. QD32 and sequential show what a parallel compiler, a big docker build or a cache archive can pull; read them after.
  • Package managers, databases and SQLite-backed tests flush their writes. Each flush waits for the storage: network disks pay a round trip every time. That is sync write.

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 ↑
x6456 runners, 9 providers
Blacksmith 4 vCPU 16 GB VM disk EPYC · model hidden nobarrier 84,854 14 µs 20,425 856,257 254,574 6.5 GiB/s 1.9 GiB/s
8 vCPU 8 vCPU 32 GB VM disk EPYC · model hidden nobarrier 76,986 13 µs 19,717 683,187 326,353 6.5 GiB/s 1.9 GiB/s
2 vCPU 2 vCPU 8 GB VM disk EPYC · model hidden nobarrier 66,914 18 µs 17,882 637,720 173,541 6.3 GiB/s 2.1 GiB/s
Namespace 8x32 8 vCPU 32 GB VM disk EPYC · model hidden 78,586 13 µs 18,160 1,108,356 412,276 4.2 GiB/s 3.0 GiB/s
8x16 8 vCPU 16 GB VM disk EPYC · model hidden 77,226 12 µs 17,740 1,120,671 476,969 4.1 GiB/s 2.9 GiB/s
4x16 4 vCPU 16 GB VM disk EPYC · model hidden 77,753 12 µs 17,773 1,007,328 406,763 4.1 GiB/s 2.9 GiB/s
4x8 4 vCPU 8 GB VM disk EPYC · model hidden 78,033 13 µs 18,087 1,015,510 403,484 4.1 GiB/s 2.9 GiB/s
2x8 2 vCPU 8 GB VM disk EPYC · model hidden 77,512 13 µs 18,068 351,146 222,814 4.1 GiB/s 2.9 GiB/s
StarSling 8 vCPU 32 GB VM disk EPYC · model hidden 56,745 17 µs 2,812 318,790 16,225 2.3 GiB/s 2.0 GiB/s
4 vCPU 4 vCPU 16 GB VM disk EPYC · model hidden volatile 53,300 17 µs 3,385 262,205 16,650 3.9 GiB/s 2.8 GiB/s
Avrea 4 vCPU 16 GB VM disk EPYC 4585PX 47,519 18 µs 8,648 468,080 246,705 6.6 GiB/s 3.5 GiB/s
8 vCPU 8 vCPU 32 GB VM disk EPYC 4585PX 42,785 19 µs 7,570 235,683 139,439 7.4 GiB/s 3.3 GiB/s
2 vCPU 2 vCPU 8 GB VM disk EPYC 4585PX 45,672 17 µs 8,163 454,466 120,725 8.4 GiB/s 6.2 GiB/s
Warpbuild 2 vCPU 8 GB VM disk Ryzen 9 9950X 24,646 59 µs 2,056 176,232 68,626 7.5 GiB/s 4.5 GiB/s
8 vCPU 8 vCPU 32 GB VM disk Ryzen 9 9950X 20,950 60 µs 1,918 120,520 45,671 7.8 GiB/s 4.9 GiB/s
4 vCPU 4 vCPU 16 GB VM disk Ryzen 9 9950X 18,708 64 µs 1,987 124,074 38,883 7.2 GiB/s 5.1 GiB/s
RunsOn i7i.2xlarge 8 vCPU 64 GB local NVMe Xeon 8559C 12,709 228 µs 11,801 300,466 165,110 2.0 GiB/s 1.5 GiB/s
m8azn.3xlarge 12 vCPU 48 GB EBS gp3 EPYC 9R05 nobarrier 1,780 782 µs 540 2,997 2,994 401 MiB/s 401 MiB/s
c8a.2xlarge 8 vCPU 16 GB EBS gp3 EPYC 9R45 nobarrier 1,781 840 µs 539 2,995 2,992 401 MiB/s 401 MiB/s
r8a.2xlarge 8 vCPU 64 GB tmpfs EPYC 9R45 1,154,342 <1 µs 433,632 4,231,165 3,828,376 18.6 GiB/s 10.1 GiB/s
m8a.2xlarge 8 vCPU 32 GB EBS gp3 EPYC 9R45 nobarrier 1,679 897 µs 538 2,994 2,992 401 MiB/s 401 MiB/s
m8a.2xlarge 8 vCPU 32 GB gp3 1000 MiB/s EPYC 9R45 nobarrier 1,774 840 µs 539 15,996 15,990 1,001 MiB/s 1,001 MiB/s
m8a.2xlarge 8 vCPU 32 GB tmpfs EPYC 9R45 1,156,332 <1 µs 432,491 4,258,470 3,812,490 18.1 GiB/s 10.0 GiB/s
m8azn.xlarge 4 vCPU 16 GB EBS gp3 EPYC 9R05 nobarrier 1,773 897 µ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,764 872 µs 539 15,994 15,991 1,001 MiB/s 1,001 MiB/s
m8i.2xlarge 8 vCPU 32 GB EBS gp3 Xeon 6975P-C nobarrier 1,569 1,012 µs 498 2,993 2,994 401 MiB/s 401 MiB/s
m8id.2xlarge 8 vCPU 32 GB local NVMe Xeon 6975P-C 10,957 228 µs 7,657 134,258 67,074 905 MiB/s 432 MiB/s
m8i-flex.2xlarge 8 vCPU 32 GB EBS gp3 Xeon 6975P-C nobarrier 1,763 872 µs 521 2,992 2,994 401 MiB/s 401 MiB/s
m8a.xlarge 4 vCPU 16 GB EBS gp3 EPYC 9R45 nobarrier 1,834 799 µs 540 2,994 2,992 401 MiB/s 401 MiB/s
c8a.xlarge 4 vCPU 8 GB EBS gp3 EPYC 9R45 nobarrier 1,790 832 µs 540 2,994 2,992 401 MiB/s 401 MiB/s
r8a.xlarge 4 vCPU 32 GB tmpfs EPYC 9R45 1,071,527 <1 µs 431,794 4,113,746 3,786,762 18.2 GiB/s 9.8 GiB/s
m8azn.large 2 vCPU 8 GB EBS gp3 EPYC 9R05 nobarrier 1,782 881 µs 542 2,994 2,992 401 MiB/s 401 MiB/s
m8i-flex.xlarge 4 vCPU 16 GB EBS gp3 Xeon 6975P-C nobarrier 1,765 774 µs 527 2,994 2,993 401 MiB/s 401 MiB/s
m8id.xlarge 4 vCPU 16 GB local NVMe Xeon 6975P-C 11,045 218 µs 7,898 67,089 33,526 451 MiB/s 216 MiB/s
m8i.xlarge 4 vCPU 16 GB EBS gp3 Xeon 6975P-C nobarrier 1,634 930 µs 521 2,992 2,994 401 MiB/s 401 MiB/s
i7i.xlarge 4 vCPU 32 GB local NVMe Xeon 8559C 11,437 301 µs 12,299 150,053 82,487 1,010 MiB/s 788 MiB/s
m8a.large 2 vCPU 8 GB EBS gp3 EPYC 9R45 nobarrier 1,826 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,844 807 µs 541 2,994 2,993 401 MiB/s 401 MiB/s
c8a.large 2 vCPU 4 GB EBS gp3 EPYC 9R45 nobarrier 1,817 807 µs 541 2,994 2,991 401 MiB/s 401 MiB/s
m8id.large 2 vCPU 8 GB local NVMe Xeon 6975P-C 10,991 228 µs 5,549 33,542 16,753 226 MiB/s 108 MiB/s
m8i.large 2 vCPU 8 GB EBS gp3 Xeon 6975P-C nobarrier 1,718 872 µs 534 2,992 2,994 401 MiB/s 401 MiB/s
i7i.large 2 vCPU 16 GB local NVMe Xeon 8559C 12,482 220 µs 13,514 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 881 µs 530 2,994 2,994 401 MiB/s 401 MiB/s
t8i.medium 2 vCPU 4 GB EBS gp3 Xeon 6975P-C nobarrier 1,750 791 µs 526 3,000 2,998 401 MiB/s 401 MiB/s
Ubicloud premium 8 vCPU 32 GB VM disk Ryzen 9 7950X3D 10,677 305 µs 4,203 374,058 28,158 3.5 GiB/s 1.4 GiB/s
standard 8 vCPU 8 vCPU 32 GB VM disk EPYC 9454P 8,407 528 µs 1,423 251,230 11,860 2.4 GiB/s 944 MiB/s
standard 4 vCPU 4 vCPU 16 GB VM disk EPYC 9454P 7,594 700 µs 578 183,661 10,621 2.4 GiB/s 494 MiB/s
premium 4 vCPU 4 vCPU 16 GB VM disk Ryzen 9 7950X3D 6,461 1,679 µs 1,395 173,146 16,062 2.5 GiB/s 537 MiB/s
standard 2 vCPU 2 vCPU 8 GB VM disk EPYC 9454 6,907 807 µs 1,870 112,843 60,676 2.7 GiB/s 806 MiB/s
premium 2 vCPU 2 vCPU 8 GB VM disk Ryzen 9 7950X3D 5,988 1,106 µs 2,417 147,821 64,867 2.7 GiB/s 867 MiB/s
GitHub 8 vCPU 32 GB VM disk EPYC 7763 nobarrier 7,942 232 µs 3,968 38,940 18,331 784 MiB/s 538 MiB/s
4-core 4 vCPU 16 GB network disk Xeon 6973P-C nobarrier 6,744 251 µs 3,082 19,578 11,682 394 MiB/s 394 MiB/s
2-core 2 vCPU 8 GB VM disk EPYC 9V45 nobarrier 6,531 289 µs 4,336 9,374 8,866 199 MiB/s 130 MiB/s
AWS CodeBuild medium 4 vCPU 8 GB EBS Xeon 8124M 1,756 758 µs 559 2,989 2,968 252 MiB/s 252 MiB/s
large 8 vCPU 16 GB EBS Xeon 8275CL 1,752 815 µs 559 2,992 2,971 252 MiB/s 252 MiB/s
small 2 vCPU 3 GB EBS Xeon 8124M 1,749 823 µs 562 2,988 2,963 252 MiB/s 252 MiB/s
arm6433 runners, 7 providers
Warpbuild xfast (Apple M4 Pro) 6 vCPU 14 GB VM disk nobarrier 26,844 41 µs 8,765 340,451 5,906 22.4 GiB/s 27.2 GiB/s
xfast (Apple M4 Pro) 12 vCPU 12 vCPU 28 GB VM disk nobarrier 25,674 52 µs 8,636 326,216 4,587 20.6 GiB/s 25.9 GiB/s
8 vCPU 8 vCPU 32 GB EBS Neoverse-V2 nobarrier 1,779 774 µs 539 4,993 4,995 401 MiB/s 401 MiB/s
4 vCPU 4 vCPU 16 GB EBS Neoverse-V2 nobarrier 1,825 823 µs 539 4,194 4,192 302 MiB/s 302 MiB/s
2 vCPU 2 vCPU 8 GB EBS Neoverse-V2 nobarrier 1,805 832 µs 538 4,195 4,193 302 MiB/s 301 MiB/s
Blacksmith 8 vCPU 32 GB VM disk Ampere-1a nobarrier 25,841 34 µs 7,676 249,115 28,207 1.6 GiB/s 944 MiB/s
4 vCPU 4 vCPU 16 GB VM disk Ampere-1a nobarrier 25,073 37 µs 7,280 167,257 25,998 1.6 GiB/s 842 MiB/s
2 vCPU 2 vCPU 6 GB VM disk Ampere-1a nobarrier 22,597 46 µs 6,166 74,915 23,744 1.6 GiB/s 813 MiB/s
Avrea 8 vCPU 32 GB VM disk Apple M5 Max · as stated by the provider 18,850 53 µs 3,848 138,687 16,621 41.6 GiB/s 15.6 GiB/s
4 vCPU 4 vCPU 16 GB VM disk Apple M5 Max · as stated by the provider 17,294 59 µs 3,664 146,383 13,857 28.9 GiB/s 13.9 GiB/s
2 vCPU 2 vCPU 8 GB VM disk Apple M5 Max · as stated by the provider 17,388 58 µs 4,222 166,284 14,173 31.4 GiB/s 15.7 GiB/s
Namespace Apple silicon 4 vCPU 16 GB VM disk CPU not reported 18,455 85 µs 3,411 148,271 17,731 30.9 GiB/s 15.4 GiB/s
8x32 8 vCPU 32 GB VM disk Ampere-1a 15,964 98 µs 3,974 179,145 40,849 942 MiB/s 763 MiB/s
8x16 8 vCPU 16 GB VM disk Ampere-1a 16,751 94 µs 3,904 188,957 52,820 923 MiB/s 748 MiB/s
4x8 4 vCPU 8 GB VM disk Ampere-1a 17,191 89 µs 3,813 145,399 32,144 994 MiB/s 739 MiB/s
4x16 4 vCPU 16 GB VM disk Ampere-1a 16,649 90 µs 3,758 141,434 36,088 978 MiB/s 738 MiB/s
2x8 2 vCPU 8 GB VM disk Ampere-1a 14,513 106 µs 3,185 62,389 24,244 941 MiB/s 696 MiB/s
RunsOn m9gd.large 2 vCPU 8 GB local NVMe Neoverse-V3 13,492 81 µs 7,267 43,606 21,782 293 MiB/s 141 MiB/s
m9gd.2xlarge 8 vCPU 32 GB local NVMe Neoverse-V3 13,464 84 µs 17,318 174,573 87,210 1.1 GiB/s 560 MiB/s
m9g.2xlarge 8 vCPU 32 GB EBS gp3 Neoverse-V3 nobarrier 1,788 807 µs 543 2,995 2,992 401 MiB/s 401 MiB/s
m9g.2xlarge 8 vCPU 32 GB tmpfs Neoverse-V3 653,143 <1 µs 301,438 2,651,587 2,495,659 14.3 GiB/s 9.1 GiB/s
c8g.2xlarge 8 vCPU 16 GB EBS gp3 Neoverse-V2 nobarrier 1,778 1,020 µs 539 2,994 2,991 401 MiB/s 401 MiB/s
m9g.xlarge 4 vCPU 16 GB EBS gp3 Neoverse-V3 nobarrier 1,568 946 µs 543 2,994 2,992 401 MiB/s 401 MiB/s
m9g.xlarge 4 vCPU 16 GB tmpfs Neoverse-V3 682,673 <1 µs 303,857 2,723,038 2,543,221 15.5 GiB/s 9.5 GiB/s
m9gd.xlarge 4 vCPU 16 GB local NVMe Neoverse-V3 12,704 134 µs 12,664 87,221 43,583 585 MiB/s 280 MiB/s
c8g.xlarge 4 vCPU 8 GB EBS gp3 Neoverse-V2 nobarrier 1,777 889 µs 539 2,994 2,994 401 MiB/s 401 MiB/s
m9g.large 2 vCPU 8 GB EBS gp3 Neoverse-V3 nobarrier 1,621 987 µs 542 2,992 2,994 401 MiB/s 401 MiB/s
c8g.large 2 vCPU 4 GB EBS gp3 Neoverse-V2 nobarrier 1,813 889 µs 537 2,993 2,994 401 MiB/s 401 MiB/s
Ubicloud standard 2 vCPU 8 GB VM disk Neoverse-N1 9,482 334 µs 4,342 93,227 55,422 937 MiB/s 608 MiB/s
standard 8 vCPU 8 vCPU 32 GB VM disk Neoverse-N1 9,278 358 µs 3,187 222,190 101,505 886 MiB/s 434 MiB/s
standard 4 vCPU 4 vCPU 16 GB VM disk Neoverse-N1 9,144 371 µs 2,132 170,177 26,833 798 MiB/s 392 MiB/s
GitHub 4 vCPU 16 GB network disk Neoverse-N2 nobarrier 8,635 202 µs 4,419 19,595 12,039 394 MiB/s 336 MiB/s
2-core 2 vCPU 8 GB VM disk Neoverse-N2 nobarrier 7,441 230 µs 3,066 9,374 6,017 199 MiB/s 163 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

  • The instance type sets the storage under the workspace: EBS gp3 by default, provisioned gp3 for bandwidth, local NVMe on the d and i families, or tmpfs when the job fits in RAM. Pick it with the family label; each one, measured: EC2 storage benchmark.

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.