Skip to content
Muhammet Şafak
tr

Go and PHP: capacity per core

Go, FrankenPHP and PHP-FPM on the same OAuth2 service: requests per core, CPU per request, PostgreSQL load and instance count.

OAuth2 service · medium confidence

Requests per second per core

  • 14,330GoGo 1.27.1
  • 6,415FrankenPHP1.12.7, worker mode
  • 5,152PHP-FPMPHP 8.5.10

On four cores

Go does 2.78 times the work of PHP-FPM.

2.23 times that of FrankenPHP. The measurement was published with medium confidence; the number is a saturation ceiling, not an SLO.

Ceiling

Requests per second on four cores

req/s

  • Go57,321
  • FrankenPHP25,659
  • PHP-FPM20,606
Read/write mix 50%/50%, PostgreSQL 17.11.

Ceiling

Req/s by core count

Ceiling req/s of Go, FrankenPHP and PHP-FPM on 1, 2 and 4 cores
CoresGoFrankenPHPPHP-FPM
116,8836,5446,218
229,44914,30611,211
457,32125,65920,606

Efficiency

CPU per request on four cores

µs

  • Go66.77
  • FrankenPHP110.74
  • PHP-FPM187.74
On a single core: 57.8 / 82.77 / 157.07 µs. FrankenPHP's CPU per request is 41% lower than PHP-FPM's.

Efficiency

FrankenPHP does not fill the core

  • 0.54Used on 1 coreGo and PHP-FPM 0.98
  • 1.44Used on 2 coresGo 1.87, PHP-FPM 1.95
  • 2.84Used on 4 coresGo 3.83, PHP-FPM 3.87

At the ceiling

Latency and memory

Read and write p50 and p99 latencies and memory use of the three candidates at the ceiling
Candidatep50 read / writep99 read / writeRSS
Go1.81 / 2.42 ms4.69 / 5.41 ms30.4 MiB
FrankenPHP4.77 / 4.96 ms8.80 / 9.06 ms60.3 MiB
PHP-FPM6.03 / 6.24 ms8.27 / 8.45 ms60.0 MiB

Database

PostgreSQL's share

The writes and reads that reach PostgreSQL as each candidate saturates, the cores it uses and its CPU per request
Saturating candidateWrites + readsPostgreSQL coresCPU per request
Go24,930 + 32,3922.3440.75 µs
FrankenPHP12,575 + 13,0841.1143.2 µs
PHP-FPM10,128 + 10,4781.4671.07 µs

Capacity

Cores needed for 30,000 req/s

  • 2.0Go
  • 3.3FrankenPHP
  • 5.6PHP-FPM

Capacity

Instance count by target rate

Instances Go, FrankenPHP and PHP-FPM need for targets between 10,000 and 100,000 req/s
Target req/sGoFrankenPHPPHP-FPM
10,000111
20,000111
30,000122
50,000123
100,000245

Tuning

Pool size and the cost of a wrong choice

The best pool size of each candidate on 1, 2 and 4 cores, and the throughput lost with the worst pool choice
CandidateBest pool (1/2/4 cores)Cost of the worst choice
Go16 / 64 / 6470.6%
PHP-FPM8 / 16 / 3230.7%
FrankenPHP8 / 8 / 829.6%

As you read

The limits of these numbers

  • CeilingThe published number is a saturation ceiling, not an SLO. 45 of 45 repetitions passed the load-generator probe.
  • EnvironmentIn one run, a headless Chromium on the host machine dropped Go to 17,490 req/s instead of 57,321; that run was discarded.
  • DiskThe VM disk's fsync guarantee was not verified; absolute write numbers may be optimistic, the comparison is not affected.

Share and download

Search the site

Start typing to search posts, projects and pages.

Escto closePowered by Pagefind