Measured · 21–23 August 2026 · Türkçe

Ten Languages,
One API


Same API. Ten languages. Three sizes. Thirty builds. All pass all tests. Then count tokens. Then measure speed, CPU, RAM.

Two big things. Token gap shrink when app grow. And token order is almost exact reverse of speed order.

30builds
259tests each, all pass
2.80×token spread
40×speed spread
57×memory spread

Three sizes

Small = plain CRUD, 7 routes. Mid = add auth, roles, row access, middleware, logging, error codes, paging, sorting, state machine, cascade delete. 16 routes. Large = add module split, ETag concurrency, idempotency keys, soft delete, audit log, outbox, quota, bulk write, search, reports, metrics, comments, user admin. 34 routes.

Spec written first. Test written second. Code written last. Nothing count until real server run and pass every test over real HTTP. Mid and large also must pass log check that read server stdout and check every log line.

Token gap shrink when app grow

Bar = cost versus cheapest language that tier. Three bars each: small, mid, large. Expensive language get much cheaper when app get big.

Python S1.00× M1.00× L1.00×
TypeScript S1.28× M1.13× L1.12×
C# S1.12× M1.08× L1.15×
Java S1.51× M1.35× L1.38×
PHP S1.94× M1.45× L1.48×
Go S1.75× M1.75× L1.56×
Rust S1.66× M1.72× L1.66×
Zig S2.08× M1.87× L1.84×
C++ S4.24× M2.50× L2.01×
C S5.05× M3.43× L2.80×
small, 7 routes mid, 16 routes large, 34 routes
Low-level penalty is fixed cost, not multiplier.

C and C++ and Zig write HTTP parser, JSON parser, JSON writer, socket loop — one time. Python and C# import all that. So Python start way ahead, then gain nothing more. Every language pay same for route number 35.

Gap worst-to-best: 5.05× at 7 routes → 3.43× at 16 → 2.80× at 34.

So: measure on toy app, you punish C too hard — by near double.

Token cost

Click any header to sort.

Languagesmallmid largelarge tokens large lines
Python1.00× 1.00×1.00× 10,5581,321
TypeScript1.28× 1.13×1.12× 11,8741,493
C#1.12× 1.08×1.15× 12,1801,360
Java1.51× 1.35×1.38× 14,5211,601
PHP1.94× 1.45×1.48× 15,6071,771
Go1.75× 1.75×1.56× 16,5182,338
Rust1.66× 1.72×1.66× 17,5602,147
Zig2.08× 1.87×1.84× 19,4181,995
C++4.24× 2.50×2.01× 21,2542,467
C5.05× 3.43×2.80× 29,5323,245

Speed, CPU, memory

Big app. 10,000 requests, one at a time. p50 = middle request. Use p50, not p99 — Windows timer tick make p99 lie. Cold start have harness floor removed.

Click any header to sort. Rank on p50 — req/s is noisy for sub-millisecond build. Detail in METHODOLOGY.md.

Languagep50 msreq/s CPU ms/reqidle RAM cold start
C++0.218 2,543 0.070 5.2 MB 58 ms
C0.240 2,084 0.059 4.2 MB 47 ms
Zig0.254 1,986 0.069 3.3 MB 57 ms
Go0.311 1,888 0.230 8.6 MB 55 ms
Rust0.327 1,412 0.150 6.2 MB 69 ms
TypeScript0.441 1,198 0.356 67.0 MB 452 ms
C#0.444 850 0.653 50.9 MB 712 ms
Java0.595 760 1.613 191.0 MB 5,275 ms
Python1.621 266 1.764 50.0 MB 1,012 ms
PHP8.636 62 5.097 34.5 MB 166 ms

Token order is reverse of speed order

Cheap tokens, slow code. Expensive tokens, fast code.

C and C++ cost most tokens — and win speed. Python cost fewest tokens — and place 9 of 10 on speed. Two lists near mirror image.

So no single best language here. Only trade you pick on purpose. Nothing sit good on both end.

Click any header to sort.

Languagetoken rankspeed rank shiftCaveman say
C++91 +8fastest, most token but one
C102 +8least CPU, fastest start, most token
Zig83 +5least RAM, 3.3 MB
Go64 +2good all round, many lines
Rust75 +2fast, safe, many token
TypeScript26 −4best mix, eat 67 MB
C#37 −4dense code, mid speed
Java48 −4JIT help later, 5 s start, 191 MB
PHP510 −5no dependency, but file store slow it
Python19 −8fewest token, slow

Shift = token rank minus speed rank. Plus mean faster than token cost suggest.

We fixed our own mistakes first

Two languages look bad because of us, not because of them.

PHP had OPcache off. php -S run CLI SAPI, where opcache.enable_cli default Off. So PHP recompile the whole app from source every request. No real deploy do that. Fixing it near halve PHP p50 on mid tier.

C and C++ had no keep-alive. Both send Connection: close every response, so new TCP handshake per request. HTTP/1.1 default is persistent. Zig — also raw socket, no framework — do it right, which prove it our bug. After fix, C small tier go 96 → 3,454 req/s, p50 11.59 → 0.166 ms. Before fix we ranked C 8th on speed. C is actually near top.

Correct keep-alive cost C and C++ about +26% token. Real trade: protocol-correct code is more code. Number here are the corrected ones.

Where PHP time really go

After OPcache fix we measured layer by layer, same server, fresh store, GET only. Answer surprise us.

Layerp50this layer add
bare PHP, no framework0.874 ms —
+ Slim boot, no store, no logic5.113 ms +4.24 ms
+ our small store and routes5.384 ms +0.27 ms
+ our large store and routes6.410 ms +1.30 ms

Bare PHP 0.874 ms — beat C# and Python. About 94% of gap is Slim container, router, middleware rebuilt from scratch every request. That is shared-nothing model, what PHP require. Not PHP language slow. Not our store slow. Every other language build router one time at startup and keep it for life of process.

So we threw the framework away. PHP now measured with no framework at all.

In Go or Rust, framework is the floor — cannot serve HTTP with less. In PHP, framework is a choice. PHP is request handler by design; one front controller on $_SERVER['REQUEST_URI'] is normal PHP, used in production. Measuring Slim charge PHP for a decision many PHP dev never make.

So PHP here is zero dependency — no composer, no vendor, no autoloader. Just public/index.php and its own file. Same store, same names, same logic. Pass same 22 / 98 / 139 test.

We measured both way before we dropped the framework one, so framework cost is a measured number, not a guess:

10,000 requestno frameworkwith Slim gain
small tier p501.362 ms 6.102 ms4.5×
mid tier p501.452 ms 6.306 ms4.3×
large tier p508.636 ms 17.588 ms2.0×
large CPU ms/req5.097 9.3551.8×
large token15,607 16,2381.04×

No framework is 4.5× faster at small, 4.3× at mid, 2.0× at large, 5× less CPU — and cost fewer token too. Plus zero manifest, because no composer file. So the framework cost about 4.2 ms every request and save nothing we measured. Old Slim run kept in perf-variance/removed-slim-run*.json so anyone can check.

These PHP number are median of three run. They hardly needed it: three run gave 1.362, 1.361, 1.376 ms at small — inside 1.1%. PHP is one of the most reproducible build in the whole benchmark. The old framework build swung 13.73, 6.07, 6.10 ms, because its autoloader touch about a hundred file per request. So the wobble was the framework, never the language.

Third PHP fix: our store was O(n)

Even with no framework, PHP looked bad at large tier. We measured why, and it was our fault again.

Store operationsmall store 501 B big store 144 KB
file_get_contents0.049 ms0.039 ms
file_put_contents0.327 ms0.741 ms
json_decode0.016 ms8.581 ms
full read + decode + encode + write0.641 ms11.519 ms

File I/O was never the problem. JSON was. Large tier grow an audit log and outbox, and our store re-serialize the whole dataset every request. So PHP pay O(total state) per request for what every other language do as O(1) append to a list in RAM. Our design, not PHP.

Fix: audit and outbox move to append-only JSON Lines file, counters in store.json so /stats and /metrics stay O(1), and a watermark so flush stay O(1) and delivered is derived not rewritten.

2,000 status change on one taskp50 start p50 enddrift
before fix7.783 ms18.402 ms2.36×
after fix7.523 ms7.547 ms1.00×

Flat. Large tier p50 drop 25.2 → 8.6 ms. Cost of the fix: +1,216 token, because O(1) persistence is more code than O(n). That move PHP from 4th to 5th on large-tier token. Honest trade, and the number here include it.

Three handicap found on PHP. All three were ours.

OPcache off. Framework rebuilt per request. Store O(n). Two of three were invisible until we measured layer by layer. Lesson: PHP shared-nothing model fight any benchmark that assume state live in memory, and a naive port quietly bill PHP for it. Read any PHP benchmark — this one too — with that in mind.

Big findings

PHP still only one that degrade

After the store fix, large tier PHP go 2.36 ms at 100 request → 8.64 ms at 10,000. Remaining growth is 1,000 soft-deleted task row sitting in the store as live domain state — which every language in the tier also hold. Legitimate, so it stay.

Framework cost PHP about 4.2 ms per request and save nothing

No framework is faster and smaller: 4.5× faster p50 at small, 4.3× at mid, 2.0× at large, 5× less CPU, and 15,607 token vs 16,238. The framework also add a composer.json and a vendor/ tree. Nothing measured here got better for it, so PHP is measured with none.

Java JIT worth 2.2×

Java get faster while run: p50 1.304 → 0.595 ms. Only big improver, drift 0.46×. But pay 5,275 ms cold start and 191 MB RAM. Fine for long server. Bad for scale-to-zero.

C use least CPU of all

0.059 CPU ms per request on big app. That is 86× less than PHP, 27× less than Java. And fastest cold start, 47 ms.

Zig use least RAM

3.3 MB idle. Java use 191 MB — 57× more. Zig do it on standard library only, zero dependency, all three tiers.

C# dense, not bloated

C# beat Python on line count at small and mid — 134 vs 138, 451 vs 472. Modern C# not old enterprise boilerplate.

Runtime spread crush token spread

Token spread 2.80×. Cold start 112×. CPU 86×. RAM 57×. Speed 40×. Source size flattest thing measured here.

Know this before you quote number