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 27,054 Warpbuild xfast (Apple M4 Pro) 6 vCPU · reads/s
GitHub's own runner 8,049 x64 QD1 reads/s on GitHub 8-core, the baseline
Fastest synced writes, x64 18,160 Namespace 8x32 · writes/s
tmpfs, for scale 1.1M 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.

Arch
Storage
QD1 random readx64 · 4k, one request in flight · IOPS, higher is better
  1. Blacksmith4 vCPUVM disk84,854, p99 14 µs, ×1.00
  2. Namespace4 vCPU4x16 · VM disk78,615, p99 12 µs, ×0.93
  3. StarSling4 vCPUVM disk53,300, p99 17 µs, ×0.63
  4. Avrea4 vCPUVM disk47,519, p99 18 µs, ×0.56
  5. Warpbuild2 vCPUVM disk26,143, p99 56 µs, ×0.31
  6. RunsOn8 vCPUi7i.2xlarge · local NVMe12,709, p99 228 µs, ×0.15
  7. Ubicloud8 vCPUpremium · VM disk9,657, p99 408 µs, ×0.11
  8. GitHub8 vCPUVM disk8,049, p99 192 µs, ×0.09
  9. AWS CodeBuild8 vCPUlarge · EBS1,763, p99 799 µs, ×0.02

tmpfs for scale: 1,127,245 on RunsOn m8a.2xlarge · tmpfs.

Synced writesx64 · 4k + fdatasync · IOPS, higher is better
  1. Namespace8 vCPU8x32 · VM disk18,160, p99 21 µs, ×1.00
  2. Blacksmith4 vCPUVM disk · nobarrier18,024, p99 32 µs, ×0.99
  3. RunsOn2 vCPUi7i.large · local NVMe13,578, p99 31 µs, ×0.75
  4. Avrea4 vCPUVM disk8,386, p99 42 µs, ×0.46
  5. GitHub8 vCPUVM disk · nobarrier3,968, p99 218 µs, ×0.22
  6. Ubicloud8 vCPUpremium · VM disk3,195, p99 774 µs, ×0.18
  7. StarSling4 vCPUVM disk3,023, p99 28 µs, ×0.17
  8. Warpbuild2 vCPUVM disk2,056, p99 111 µs, ×0.11
  9. AWS CodeBuild2 vCPUsmall · EBS562, p99 991 µ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,127,245, p99 <1 µs, ×13
  2. RunsOn8 vCPUr8a.2xlarge · tmpfs · RAM1,098,003, p99 <1 µs, ×13
  3. RunsOn4 vCPUr8a.xlarge · tmpfs · RAM1,054,041, p99 <1 µs, ×12
  4. Blacksmith4 vCPUVM disk84,854, p99 14 µs, ×1.00
  5. Namespace4 vCPU4x16 · VM disk78,615, p99 12 µs, ×0.93
  6. StarSling4 vCPUVM disk53,300, p99 17 µs, ×0.63
  7. Avrea4 vCPUVM disk47,519, p99 18 µs, ×0.56
  8. Warpbuild2 vCPUVM disk26,143, p99 56 µs, ×0.31
  9. RunsOn8 vCPUi7i.2xlarge · local NVMe12,709, p99 228 µs, ×0.15
  10. Ubicloud8 vCPUpremium · VM disk9,657, p99 408 µs, ×0.11
  11. GitHub8 vCPUVM disk8,049, p99 192 µs, ×0.09
  12. AWS CodeBuild8 vCPUlarge · EBS1,763, p99 799 µs, ×0.02

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

Synced writesx64 · 4k + fdatasync · IOPS, higher is better
  1. RunsOn4 vCPUr8a.xlarge · tmpfs · RAM912,188, p99 <1 µs, ×50
  2. RunsOn8 vCPUr8a.2xlarge · tmpfs · RAM877,674, p99 <1 µs, ×48
  3. RunsOn8 vCPUm8a.2xlarge · tmpfs · RAM664,801, p99 <1 µs, ×37
  4. Namespace8 vCPU8x32 · VM disk18,160, p99 21 µs, ×1.00
  5. Blacksmith4 vCPUVM disk · nobarrier18,024, p99 32 µs, ×0.99
  6. RunsOn2 vCPUi7i.large · local NVMe13,578, p99 31 µs, ×0.75
  7. Avrea4 vCPUVM disk8,386, p99 42 µs, ×0.46
  8. GitHub8 vCPUVM disk · nobarrier3,968, p99 218 µs, ×0.22
  9. Ubicloud8 vCPUpremium · VM disk3,195, p99 774 µs, ×0.18
  10. StarSling4 vCPUVM disk3,023, p99 28 µs, ×0.17
  11. Warpbuild2 vCPUVM disk2,056, p99 111 µs, ×0.11
  12. AWS CodeBuild2 vCPUsmall · EBS562, p99 991 µ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 disk27,054, p99 39 µs, ×1.00
  2. Blacksmith8 vCPUVM disk25,355, p99 38 µs, ×0.94
  3. Namespace4 vCPUApple silicon · VM disk20,208, p99 80 µs, ×0.75
  4. Avrea8 vCPUVM disk18,297, p99 56 µs, ×0.68
  5. RunsOn8 vCPUm9gd.2xlarge · local NVMe14,947, p99 72 µs, ×0.55
  6. Ubicloud8 vCPUstandard · VM disk9,614, p99 330 µs, ×0.36
  7. GitHub4 vCPUnetwork disk8,635, p99 202 µs, ×0.32

tmpfs for scale: 674,926 on RunsOn m9g.xlarge · tmpfs.

Synced writesarm64 · 4k + fdatasync · IOPS, higher is better
  1. RunsOn8 vCPUm9gd.2xlarge · local NVMe16,257, p99 21 µs, ×1.00
  2. Warpbuild6 vCPUxfast (Apple M4 Pro) · VM disk · nobarrier8,615, p99 52 µs, ×0.53
  3. Blacksmith8 vCPUVM disk · nobarrier7,306, p99 75 µs, ×0.45
  4. GitHub4 vCPUnetwork disk · nobarrier4,666, p99 257 µs, ×0.29
  5. Ubicloud2 vCPUstandard · VM disk4,319, p99 412 µs, ×0.27
  6. Namespace8 vCPU8x16 · VM disk4,004, p99 165 µs, ×0.25
  7. Avrea2 vCPUVM disk3,985, p99 57 µs, ×0.25

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 · RAM674,926, p99 <1 µs, ×25
  2. RunsOn8 vCPUm9g.2xlarge · tmpfs · RAM625,966, p99 <1 µs, ×23
  3. Warpbuild6 vCPUxfast (Apple M4 Pro) · VM disk27,054, p99 39 µs, ×1.00
  4. Blacksmith8 vCPUVM disk25,355, p99 38 µs, ×0.94
  5. Namespace4 vCPUApple silicon · VM disk20,208, p99 80 µs, ×0.75
  6. Avrea8 vCPUVM disk18,297, p99 56 µs, ×0.68
  7. RunsOn8 vCPUm9gd.2xlarge · local NVMe14,947, p99 72 µs, ×0.55
  8. Ubicloud8 vCPUstandard · VM disk9,614, p99 330 µs, ×0.36
  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 · RAM634,741, p99 <1 µs, ×39
  2. RunsOn8 vCPUm9g.2xlarge · tmpfs · RAM470,633, p99 <1 µs, ×29
  3. RunsOn8 vCPUm9gd.2xlarge · local NVMe16,257, p99 21 µs, ×1.00
  4. Warpbuild6 vCPUxfast (Apple M4 Pro) · VM disk · nobarrier8,615, p99 52 µs, ×0.53
  5. Blacksmith8 vCPUVM disk · nobarrier7,306, p99 75 µs, ×0.45
  6. GitHub4 vCPUnetwork disk · nobarrier4,666, p99 257 µs, ×0.29
  7. Ubicloud2 vCPUstandard · VM disk4,319, p99 412 µs, ×0.27
  8. Namespace8 vCPU8x16 · VM disk4,004, p99 165 µs, ×0.25
  9. Avrea2 vCPUVM disk3,985, p99 57 µs, ×0.25

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,559 on RunsOn m8i.2xlarge · EBS gp3, 54× apart; p99 latency is 14 µs against 1,036 µs.
  • Synced 4k writes on x64 run from 470 per second on RunsOn m8i.2xlarge · EBS gp3 (workspace mounted nobarrier) to 18,160 on Namespace 8x32.
  • r8a.xlarge with tmpfs ($0.0021/min at spot) answers 1,054,041 QD1 reads and 912,188 synced writes per second: 87× and 77× the best local NVMe at 4 vCPU (i7i.xlarge, $0.0019) and 577× and 1,692× 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,559 and 1,842 QD1 reads and 470 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 27,054 times a second on Warpbuild xfast (Apple M4 Pro) 6 vCPU and 1,660 on RunsOn m9g.large · EBS gp3, 16× apart; p99 latency is 39 µs against 963 µs.
  • Synced 4k writes on arm64 run from 538 per second on Warpbuild 2 vCPU (workspace mounted nobarrier) to 16,257 on RunsOn m9gd.2xlarge · local NVMe.
  • Same Xeon 6975P-C CPU, different disk: m8id.2xlarge on local NVMe answers 11,168 QD1 reads and 7,657 synced writes per second, m8i.2xlarge on EBS gp3 1,559 and 470.
  • Same Xeon 6975P-C CPU, different disk: m8id.large on local NVMe answers 10,850 QD1 reads and 5,551 synced writes per second, m8i-flex.large on EBS gp3 1,745 and 527.
  • Same Xeon 6975P-C CPU, different disk: m8id.xlarge on local NVMe answers 11,056 QD1 reads and 7,841 synced writes per second, m8i-flex.xlarge on EBS gp3 1,576 and 527.
  • Same Neoverse-V3 CPU, different disk: m9gd.2xlarge on local NVMe answers 14,947 QD1 reads and 16,257 synced writes per second, m9g.2xlarge on EBS gp3 1,720 and 543.
  • Same Neoverse-V3 CPU, different disk: m9gd.xlarge on local NVMe answers 12,610 QD1 reads and 11,264 synced writes per second, m9g.xlarge on EBS gp3 1,818 and 543.
  • Same Neoverse-V3 CPU, different disk: m9gd.large on local NVMe answers 13,526 QD1 reads and 7,159 synced writes per second, m9g.large on EBS gp3 1,660 and 543.
  • 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,002 MiB/s (2.5×); QD1 reads barely move (1,775 → 1,775 IOPS): it buys bandwidth, not latency.
  • tmpfs on m8a.2xlarge is not a disk at all: 1,127,245 QD1 reads and 664,801 synced writes per second, from RAM. The workspace is 31 GiB, sized by memory.
  • tmpfs on m9g.2xlarge is not a disk at all: 625,966 QD1 reads and 470,633 synced writes per second, from RAM. The workspace is 31 GiB, sized by memory.
  • tmpfs on m9g.xlarge is not a disk at all: 674,926 QD1 reads and 634,741 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,098,003 QD1 reads and 877,674 synced writes per second, from RAM. The workspace is 62 GiB, sized by memory.
  • tmpfs: 626k–1.1M QD1 reads and 471k–912k synced writes per second across 5 runners (5 RunsOn configurations).
  • VM disk: 3.8k–85k QD1 reads and 578–18k 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–15k QD1 reads and 5.6k–16k synced writes per second across 9 runners (9 RunsOn configurations).
  • network disk: 6.8k–8.6k QD1 reads and 3.3k–4.7k synced writes per second across 2 runners (2 GitHub runners).
  • EBS: 1.6k–1.8k QD1 reads and 470–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 18,024 873,112 251,762 6.9 GiB/s 1.6 GiB/s
8 vCPU 8 vCPU 32 GB VM disk EPYC · model hidden nobarrier 68,500 19 µs 15,392 567,996 199,982 4.0 GiB/s 1.7 GiB/s
2 vCPU 2 vCPU 8 GB VM disk EPYC · model hidden nobarrier 61,629 19 µs 15,532 515,353 136,106 4.7 GiB/s 1.9 GiB/s
Namespace 4x16 4 vCPU 16 GB VM disk EPYC · model hidden 78,615 12 µs 17,844 1,011,926 436,056 4.1 GiB/s 2.9 GiB/s
8x32 8 vCPU 32 GB VM disk EPYC · model hidden 78,586 13 µs 18,160 1,126,282 417,764 4.2 GiB/s 2.9 GiB/s
8x16 8 vCPU 16 GB VM disk EPYC · model hidden 78,141 12 µs 17,901 1,137,038 423,854 4.1 GiB/s 2.9 GiB/s
4x8 4 vCPU 8 GB VM disk EPYC · model hidden 78,033 12 µs 17,941 1,009,155 403,484 4.1 GiB/s 3.0 GiB/s
2x8 2 vCPU 8 GB VM disk EPYC · model hidden 77,512 13 µs 18,068 350,533 222,621 4.1 GiB/s 2.9 GiB/s
StarSling 4 vCPU 16 GB VM disk EPYC · model hidden 53,300 17 µs 3,023 262,205 11,527 2.5 GiB/s 3.4 GiB/s
8 vCPU 8 vCPU 32 GB VM disk EPYC · model hidden 52,315 18 µs 2,812 318,790 10,959 2.5 GiB/s 2.0 GiB/s
Avrea 4 vCPU 16 GB VM disk EPYC 4585PX 47,519 18 µs 8,386 402,481 172,765 4.6 GiB/s 3.1 GiB/s
8 vCPU 8 vCPU 32 GB VM disk EPYC 4585PX 43,414 23 µs 7,763 245,805 139,439 7.4 GiB/s 5.4 GiB/s
2 vCPU 2 vCPU 8 GB VM disk EPYC 4585PX 45,672 20 µs 8,163 454,066 132,755 5.3 GiB/s 3.4 GiB/s
Warpbuild 2 vCPU 8 GB VM disk Ryzen 9 9950X 26,143 56 µs 2,056 151,759 72,474 7.6 GiB/s 4.6 GiB/s
8 vCPU 8 vCPU 32 GB VM disk Ryzen 9 9950X 19,636 60 µs 1,813 98,888 44,952 7.9 GiB/s 4.5 GiB/s
4 vCPU 4 vCPU 16 GB VM disk Ryzen 9 9950X 22,245 58 µs 1,980 143,694 40,569 7.8 GiB/s 5.1 GiB/s
RunsOn i7i.2xlarge 8 vCPU 64 GB local NVMe Xeon 8559C 12,709 228 µs 11,496 300,466 165,109 2.0 GiB/s 1.5 GiB/s
m8azn.3xlarge 12 vCPU 48 GB EBS gp3 EPYC 9R05 nobarrier 1,827 766 µs 539 2,997 2,996 401 MiB/s 401 MiB/s
c8a.2xlarge 8 vCPU 16 GB EBS gp3 EPYC 9R45 nobarrier 1,796 832 µs 539 2,995 2,992 401 MiB/s 401 MiB/s
m8a.2xlarge 8 vCPU 32 GB EBS gp3 EPYC 9R45 nobarrier 1,770 856 µs 538 2,995 2,991 401 MiB/s 401 MiB/s
m8a.2xlarge 8 vCPU 32 GB gp3 1000 MiB/s EPYC 9R45 nobarrier 1,677 897 µs 538 15,995 15,993 1,001 MiB/s 1,001 MiB/s
r8a.2xlarge 8 vCPU 64 GB tmpfs EPYC 9R45 1,098,003 <1 µs 877,674 4,207,889 3,669,702 18.5 GiB/s 10.1 GiB/s
m8a.2xlarge 8 vCPU 32 GB tmpfs EPYC 9R45 1,127,245 <1 µs 664,801 4,214,475 3,756,731 18.4 GiB/s 10.0 GiB/s
m8azn.xlarge 4 vCPU 16 GB EBS gp3 EPYC 9R05 nobarrier 1,775 963 µs 541 2,994 2,992 401 MiB/s 401 MiB/s
m8azn.xlarge 4 vCPU 16 GB gp3 1000 MiB/s EPYC 9R05 nobarrier 1,775 856 µs 540 15,994 15,991 1,002 MiB/s 1,001 MiB/s
m8id.2xlarge 8 vCPU 32 GB local NVMe Xeon 6975P-C 11,168 169 µs 7,657 134,258 67,074 905 MiB/s 432 MiB/s
m8i.2xlarge 8 vCPU 32 GB EBS gp3 Xeon 6975P-C nobarrier 1,559 1,036 µs 470 2,992 2,994 401 MiB/s 401 MiB/s
m8a.xlarge 4 vCPU 16 GB EBS gp3 EPYC 9R45 nobarrier 1,828 840 µs 539 2,993 2,993 401 MiB/s 401 MiB/s
m8i-flex.2xlarge 8 vCPU 32 GB EBS gp3 Xeon 6975P-C nobarrier 1,746 848 µs 516 2,992 2,995 401 MiB/s 401 MiB/s
c8a.xlarge 4 vCPU 8 GB EBS gp3 EPYC 9R45 nobarrier 1,745 930 µs 540 2,994 2,993 401 MiB/s 401 MiB/s
r8a.xlarge 4 vCPU 32 GB tmpfs EPYC 9R45 1,054,041 <1 µs 912,188 4,014,510 3,665,859 18.2 GiB/s 9.9 GiB/s
m8azn.large 2 vCPU 8 GB EBS gp3 EPYC 9R05 nobarrier 1,840 856 µs 542 2,992 2,993 401 MiB/s 401 MiB/s
m8i-flex.xlarge 4 vCPU 16 GB EBS gp3 Xeon 6975P-C nobarrier 1,576 963 µs 527 2,994 2,993 401 MiB/s 401 MiB/s
m8id.xlarge 4 vCPU 16 GB local NVMe Xeon 6975P-C 11,056 210 µs 7,841 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 508 2,992 2,994 401 MiB/s 401 MiB/s
i7i.xlarge 4 vCPU 32 GB local NVMe Xeon 8559C 12,069 307 µs 12,095 150,053 82,488 1,010 MiB/s 788 MiB/s
r8a.large 2 vCPU 16 GB EBS gp3 EPYC 9R45 nobarrier 1,842 881 µs 541 2,991 2,994 401 MiB/s 401 MiB/s
m8a.large 2 vCPU 8 GB EBS gp3 EPYC 9R45 nobarrier 1,749 770 µs 541 2,994 2,993 401 MiB/s 401 MiB/s
c8a.large 2 vCPU 4 GB EBS gp3 EPYC 9R45 nobarrier 1,809 807 µs 541 2,991 2,993 401 MiB/s 401 MiB/s
m8id.large 2 vCPU 8 GB local NVMe Xeon 6975P-C 10,850 229 µs 5,551 33,542 16,753 225 MiB/s 108 MiB/s
m8i.large 2 vCPU 8 GB EBS gp3 Xeon 6975P-C nobarrier 1,736 872 µs 534 2,993 2,994 401 MiB/s 401 MiB/s
i7i.large 2 vCPU 16 GB local NVMe Xeon 8559C 12,482 212 µs 13,578 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 527 2,994 2,994 401 MiB/s 401 MiB/s
t8i.medium 2 vCPU 4 GB EBS gp3 Xeon 6975P-C nobarrier 1,750 799 µs 524 3,000 2,998 401 MiB/s 401 MiB/s
Ubicloud premium 8 vCPU 32 GB VM disk Ryzen 9 7950X3D 9,657 408 µs 3,195 362,984 19,859 3.1 GiB/s 1.2 GiB/s
standard 8 vCPU 8 vCPU 32 GB VM disk EPYC 9454P 8,407 569 µs 1,670 264,258 11,860 2.6 GiB/s 689 MiB/s
premium 4 vCPU 4 vCPU 16 GB VM disk Ryzen 9 7950X3D 8,328 1,679 µs 1,343 210,832 16,062 2.7 GiB/s 807 MiB/s
standard 4 vCPU 4 vCPU 16 GB VM disk EPYC 9454P 3,805 2,073 µs 578 157,238 8,344 2.2 GiB/s 250 MiB/s
standard 2 vCPU 2 vCPU 8 GB VM disk EPYC 9454P 6,847 864 µs 1,549 106,887 46,311 2.3 GiB/s 398 MiB/s
premium 2 vCPU 2 vCPU 8 GB VM disk Ryzen 9 7950X3D 5,988 1,106 µs 2,391 138,040 64,617 2.8 GiB/s 833 MiB/s
GitHub 8 vCPU 32 GB VM disk Xeon 8573C nobarrier 8,049 192 µs 3,968 38,954 18,761 784 MiB/s 532 MiB/s
4-core 4 vCPU 16 GB network disk EPYC 7763 nobarrier 6,843 251 µs 3,262 19,587 11,712 394 MiB/s 394 MiB/s
2-core 2 vCPU 8 GB VM disk EPYC 7763 nobarrier 6,531 289 µs 3,904 9,378 8,712 199 MiB/s 199 MiB/s
AWS CodeBuild large 8 vCPU 16 GB EBS Xeon 8124M 1,763 799 µs 559 2,988 2,970 252 MiB/s 252 MiB/s
medium 4 vCPU 8 GB EBS Xeon 8275CL 1,748 778 µs 559 2,990 2,967 252 MiB/s 252 MiB/s
small 2 vCPU 3 GB EBS Xeon 8124M 1,755 791 µs 562 2,988 2,969 252 MiB/s 252 MiB/s
arm6433 runners, 7 providers
Warpbuild xfast (Apple M4 Pro) 6 vCPU 14 GB VM disk nobarrier 27,054 39 µs 8,615 338,802 5,322 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,410 334,760 5,979 19.8 GiB/s 26.8 GiB/s
8 vCPU 8 vCPU 32 GB EBS Neoverse-V2 nobarrier 1,776 807 µs 539 4,993 4,995 401 MiB/s 401 MiB/s
4 vCPU 4 vCPU 16 GB EBS Neoverse-V2 nobarrier 1,814 807 µs 539 4,195 4,193 301 MiB/s 302 MiB/s
2 vCPU 2 vCPU 8 GB EBS Neoverse-V2 nobarrier 1,784 832 µs 538 4,194 4,193 302 MiB/s 301 MiB/s
Blacksmith 8 vCPU 32 GB VM disk Ampere-1a nobarrier 25,355 38 µs 7,306 223,621 27,644 1.6 GiB/s 940 MiB/s
4 vCPU 4 vCPU 16 GB VM disk Ampere-1a nobarrier 24,897 39 µs 7,118 155,975 24,132 1.7 GiB/s 742 MiB/s
2 vCPU 2 vCPU 6 GB VM disk Ampere-1a nobarrier 22,597 46 µs 6,166 77,706 23,744 1.5 GiB/s 775 MiB/s
Namespace Apple silicon 4 vCPU 16 GB VM disk CPU not reported 20,208 80 µs 3,489 143,397 15,978 32.9 GiB/s 15.4 GiB/s
8x16 8 vCPU 16 GB VM disk Ampere-1a 16,751 93 µs 4,004 188,888 61,821 990 MiB/s 748 MiB/s
8x32 8 vCPU 32 GB VM disk Ampere-1a 16,284 98 µs 3,252 186,558 32,721 953 MiB/s 763 MiB/s
4x16 4 vCPU 16 GB VM disk Ampere-1a 17,304 90 µs 3,860 144,335 39,744 969 MiB/s 738 MiB/s
4x8 4 vCPU 8 GB VM disk Ampere-1a 17,048 90 µs 3,813 145,399 29,784 988 MiB/s 756 MiB/s
2x8 2 vCPU 8 GB VM disk Ampere-1a 16,399 106 µs 3,877 77,649 24,244 921 MiB/s 736 MiB/s
Avrea 8 vCPU 32 GB VM disk Apple M5 Max · as stated by the provider 18,297 56 µs 3,844 137,885 15,642 36.5 GiB/s 15.6 GiB/s
4 vCPU 4 vCPU 16 GB VM disk Apple M5 Max · as stated by the provider 17,515 55 µs 3,932 146,579 15,032 28.9 GiB/s 13.7 GiB/s
2 vCPU 2 vCPU 8 GB VM disk Apple M5 Max · as stated by the provider 17,564 59 µs 3,985 165,024 14,173 31.7 GiB/s 14.0 GiB/s
RunsOn m9gd.2xlarge 8 vCPU 32 GB local NVMe Neoverse-V3 14,947 72 µs 16,257 174,573 87,210 1.1 GiB/s 560 MiB/s
m9g.2xlarge 8 vCPU 32 GB EBS gp3 Neoverse-V3 nobarrier 1,720 823 µs 543 2,995 2,993 401 MiB/s 401 MiB/s
m9g.2xlarge 8 vCPU 32 GB tmpfs Neoverse-V3 625,966 <1 µs 470,633 2,537,608 2,410,790 11.6 GiB/s 4.0 GiB/s
c8g.2xlarge 8 vCPU 16 GB EBS gp3 Neoverse-V2 nobarrier 1,817 815 µs 540 2,994 2,994 401 MiB/s 401 MiB/s
m9g.xlarge 4 vCPU 16 GB EBS gp3 Neoverse-V3 nobarrier 1,818 938 µs 543 2,994 2,993 401 MiB/s 401 MiB/s
m9g.xlarge 4 vCPU 16 GB tmpfs Neoverse-V3 674,926 <1 µs 634,741 2,690,916 2,487,599 15.1 GiB/s 4.6 GiB/s
m9gd.xlarge 4 vCPU 16 GB local NVMe Neoverse-V3 12,610 138 µs 11,264 87,221 43,583 585 MiB/s 280 MiB/s
c8g.xlarge 4 vCPU 8 GB EBS gp3 Neoverse-V2 nobarrier 1,703 889 µs 539 2,992 2,994 401 MiB/s 401 MiB/s
m9gd.large 2 vCPU 8 GB local NVMe Neoverse-V3 13,526 81 µs 7,159 43,607 21,782 293 MiB/s 141 MiB/s
m9g.large 2 vCPU 8 GB EBS gp3 Neoverse-V3 nobarrier 1,660 963 µs 543 2,992 2,994 401 MiB/s 401 MiB/s
c8g.large 2 vCPU 4 GB EBS gp3 Neoverse-V2 nobarrier 1,779 815 µs 539 2,993 2,994 401 MiB/s 401 MiB/s
Ubicloud standard 8 vCPU 32 GB VM disk Neoverse-N1 9,614 330 µs 2,433 211,987 101,505 832 MiB/s 438 MiB/s
standard 4 vCPU 4 vCPU 16 GB VM disk Neoverse-N1 7,201 610 µs 2,132 158,274 57,360 836 MiB/s 351 MiB/s
standard 2 vCPU 2 vCPU 8 GB VM disk Neoverse-N1 9,284 317 µs 4,319 107,365 78,893 929 MiB/s 637 MiB/s
GitHub 4 vCPU 16 GB network disk Neoverse-N2 nobarrier 8,635 202 µs 4,666 19,588 11,775 394 MiB/s 337 MiB/s
2-core 2 vCPU 8 GB VM disk Neoverse-N2 nobarrier 7,143 264 µs 3,066 9,377 6,407 200 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.