Measured · 21–23 August 2026 · detailed version · Türkçe (kısa sürüm)
Same API. Ten languages. Three sizes. Thirty builds. All pass all tests. Then count tokens. Then measure cold start, latency, throughput, CPU and RAM at 100, 1,000 and 10,000 requests.
This is the long version: every table, every tier, and every mistake we made
and fixed. Short version at docs/benchmark.html.
| Tier | routes | tests | What it add |
|---|---|---|---|
| small | 7 | 22 | CRUD, validation, derived field, two-key sort, aggregate with rounded mean and nullable field |
| mid | 16 | 98 | session auth, roles, row-level access, middleware chain, structured JSON log, error envelope with machine codes and request id, multi-error validation, paging, whitelisted sort, status state machine, cascade delete, conflicts |
| large | 34 | 139 | forced 4-module split, ETag + If-Match concurrency, idempotency keys with replay, soft delete and restore, audit trail, outbox, per-session quota, bulk write with per-item result, search, grouped reports, metrics by route pattern, comments, user admin, admin-only field |
Large tier force a module split: domain,
store, service, api, each import only from above.
That is real enterprise shape, and it is where a language with no module pay twice — C and
C++ must write a header per module. C three header alone = 368 of its 3,245 line.
Nothing count until it work. Two gate, both must pass.
Real HTTP against a live server on port 8080. No mock. Check status code, exact
top-level key set, every value, list order, validation-detail order, and headers
X-Request-Id, ETag, X-Quota-Remaining,
Idempotency-Replayed. Float compare with 1e-9 tolerance, everything else
exact.
Mid and large only. A tool read server stdout and check every log line: one
JSON object per line, exact key order, level match status class, no query string in
path, right type each field. Spec also say nothing but log go to stdout,
so each build must silence its own framework.
Order of work each tier: spec first, test second, then one Python reference driven to a full pass, then the other nine. Every build re-verified by hand, separate from the report it came with. Result: 30/30 pass 22 / 98 / 139, and all 20 mid and large build pass the log check.
All three found by asking why a number looked worse than it should. All three fixed
before publish. Old data kept for audit in perf-results-before-*.json.
php -S run the CLI SAPI, where opcache.enable_cli
default Off. So PHP recompile the whole app from source
every request. No production PHP run that way.
Both send Connection: close every response, so a new TCP handshake
per request. HTTP/1.1 default is a persistent connection. Zig also hand-write raw socket
with no framework, and Zig do keep-alive right — that is what prove this our defect, not a
property of C.
| Small tier, 10,000 request | before | after | change |
|---|---|---|---|
| C p50 | 11.587 ms | 0.166 ms | 70× faster |
| C req/s | 96 | 3,454 | 36× more |
| C++ p50 | 11.164 ms | 0.200 ms | 56× faster |
| C++ req/s | 99 | 2,561 | 26× more |
Before the fix we ranked C 8th on speed. C is actually near the top. The fix
also add safety: cap 1,000 request per connection, SO_RCVTIMEO 5 s so one idle
client cannot deadlock a single-thread accept loop, and TCP_NODELAY in C
because it write header and body as two send and Nagle would stall the second.
Correct keep-alive cost C about +26% token. Protocol-correct code is more
code. Every number here include that.
Covered in full in the next section. Short version: the large tier grow an audit log, and our store re-serialize the whole dataset every request, so PHP paid O(total state) per request for what every other language do as an O(1) append to a list in RAM.
Everything else reviewed for the same kind of handicap and found fair: all
ten run a single process with default framework setting, the compiled language all build
in standard release mode (-O2, --release,
ReleaseSafe), and no language get a tuning flag another is denied.
PHP looked far worse than any of us expected, so we took it apart layer by layer. Same server, fresh store, GET only, warm. Three separate things were wrong, and all three were ours.
| Layer | p50 | this layer add |
|---|---|---|
| bare PHP, no framework | 0.874 ms | — |
| + Slim construct, no store, no logic | 5.113 ms | +4.24 ms |
| + our small-tier store and routes | 5.384 ms | +0.27 ms |
| + our large-tier store and routes | 6.410 ms | +1.30 ms |
Bare PHP 0.874 ms — faster than C# and faster than Python. About 94% of the gap was Slim container, router and middleware stack built from scratch on every request. That is what shared-nothing require. Every other language here build its router one time at startup and keep it for the life of the process.
You cannot serve HTTP in Go with less than net/http. PHP is a request
handler by design, and one front controller on $_SERVER['REQUEST_URI'] is
ordinary production PHP. Measuring Slim charge PHP for a decision many PHP developer
never make.
So PHP here carry zero dependency at all three tier — no composer, no
vendor, no autoloader, just public/index.php and its own file. Same store,
same identifier name, same logic. Pass the same 22 / 98 / 139 test. Only the HTTP layer
differ from the old framework build.
We measured both way before we dropped the framework one, so the framework cost
below is a measured number, not a guess. The old run stay in
perf-variance/removed-slim-run*.json.
| Store operation | small store 501 B | big store 144 KB |
|---|---|---|
| file_get_contents | 0.049 ms | 0.039 ms |
| file_put_contents | 0.327 ms | 0.741 ms |
| json_decode | 0.016 ms | 8.581 ms |
| full read + decode + encode + write | 0.641 ms | 11.519 ms |
File I/O was never the problem. JSON serialization was. With a
fresh store, PHP answer GET /health at the large tier in
1.656 ms — healthy, same range as Python. After a 10,000-request run it had
degraded to 25.2 ms, because the audit trail and outbox grow and our store rewrote the whole
dataset each time.
Fix: audit and outbox move to append-only JSON Lines file written with
FILE_APPEND and never rewritten; auditCount,
outboxCount and outboxDelivered counter in store.json
so /stats and /metrics stay O(1); and an
outboxFlushedThrough watermark so flush stay O(1) and each event
delivered flag is derived on read rather than rewritten.
| 2,000 status change on one task, so only audit grow | p50 start | p50 end | drift |
|---|---|---|---|
| before fix | 7.783 ms | 18.402 ms | 2.36× |
| after fix | 7.523 ms | 7.547 ms | 1.00× |
Flat. Large tier p50 drop 25.2 → 8.6 ms. Cost: +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 every number here include it.
A mixed create-and-delete workload still drift after the fix, but that residue
is not the audit trail: it soft-delete 1,000 task, and those row stay in
store.json as live domain state that every build in the tier also hold. That
part is legitimate and stay.
| 10,000 request | no framework | with Slim 4 | gain |
|---|---|---|---|
| small tier p50 | 1.362 ms | 6.102 ms | 4.5× |
| mid tier p50 | 1.452 ms | 6.306 ms | 4.3× |
| large tier p50 | 8.636 ms | 17.588 ms | 2.0× |
| small CPU ms/req | 0.736 | 4.770 | 6.5× |
| mid CPU ms/req | 0.901 | 5.012 | 5.6× |
| large CPU ms/req | 5.097 | 9.355 | 1.8× |
| large token | 15,607 | 16,238 | 1.04× |
No framework also cost fewer token: 15,607 against 16,238 at the large tier, plus zero manifest because there is no composer file. So Slim cost about 4.2 ms per request, roughly 4% more token, a manifest and a vendor tree — and nothing measured here got better for it. That is why PHP is published with no framework.
PHP repeat tight: small tier gave 1.362, 1.361, 1.376 ms, mid gave 1.452, 1.457, 1.448 ms, large gave 8.418, 8.636, 8.779 ms. Spread 1.1%, 0.6%, 4.3%. One of the most reproducible build in the whole benchmark, because a millisecond of real work swamp a 15.6 ms timer artifact that a sub-millisecond server cannot absorb.
Worth saying because the old framework build swung 13.73, 6.07, 6.10 ms
at small and 14.12, 6.31, 6.28 ms at mid: its Composer autoloader touch
about a hundred file per request and page-cache state decide the number. So the instability
belonged to the framework, never the language. perf-variance/ hold every raw
repeat, old build included.
Honest summary. PHP is not a slow language. Three separate handicap were stacked on it and all three were ours. What remain after removing them is the shared-nothing execution model itself: PHP cannot hold state between request, and this benchmark forbid a database, so PHP must serialize something on every request while the other nine keep everything in RAM for free. A persistent runtime — Swoole, RoadRunner, FrankenPHP — remove that too. Not tested here.
Bar = cost versus the cheapest build that tier. Right-hand number = change in ratio small to large; minus mean the gap closed.
C, C++ and Zig write an HTTP parser, a JSON parser, a JSON writer and a socket loop one time. Python and C# import all of it. Python start way ahead then gain nothing more. Every build pay about the same for route 35.
Gap worst-to-best: 5.05× at 7 routes → 3.43× at 16 → 2.80× at 34. C++ shed 2.23×, C shed 2.25×.
Measure on a toy app and you punish C by near double what a real app would show.
Token from tiktoken o200k_base. A second encoder,
cl100k_base, give the same order at every tier — that is the evidence the
ranking belong to the source, not the encoder. Code line exclude blank and comment line.
Click any header to sort.
| Language | Framework | lines | code | chars | tokens | ratio | cl100k |
|---|---|---|---|---|---|---|---|
| Python | FastAPI | 138 | 101 | 3,833 | 986 | 1.00× | 982 |
| C# | Minimal API | 134 | 111 | 4,316 | 1,100 | 1.12× | 1,082 |
| TypeScript | Express | 152 | 130 | 4,575 | 1,259 | 1.28× | 1,259 |
| Java | Spring Boot | 172 | 150 | 7,007 | 1,489 | 1.51× | 1,405 |
| Rust | Axum | 211 | 192 | 6,415 | 1,637 | 1.66× | 1,631 |
| Go | net/http | 263 | 236 | 6,154 | 1,722 | 1.75× | 1,672 |
| PHP | no framework | 247 | 219 | 7,166 | 1,911 | 1.94× | 1,895 |
| Zig | std.http | 211 | 186 | 7,596 | 2,047 | 2.08× | 2,038 |
| C++ | raw winsock | 456 | 412 | 16,158 | 4,179 | 4.24× | 4,178 |
| C | raw winsock | 593 | 545 | 18,403 | 4,981 | 5.05× | 4,962 |
| Language | lines | code | chars | tokens | ratio | cl100k |
|---|---|---|---|---|---|---|
| Python | 472 | 369 | 15,218 | 3,761 | 1.00× | 3,751 |
| C# | 451 | 397 | 16,599 | 4,054 | 1.08× | 3,963 |
| TypeScript | 513 | 458 | 16,362 | 4,250 | 1.13× | 4,216 |
| Java | 550 | 490 | 23,652 | 5,094 | 1.35× | 4,842 |
| PHP | 625 | 555 | 20,450 | 5,464 | 1.45× | 5,433 |
| Rust | 833 | 778 | 25,372 | 6,484 | 1.72× | 6,458 |
| Go | 946 | 877 | 23,400 | 6,589 | 1.75× | 6,525 |
| Zig | 692 | 636 | 26,120 | 7,022 | 1.87× | 6,986 |
| C++ | 1,044 | 947 | 37,391 | 9,385 | 2.50× | 9,341 |
| C | 1,532 | 1,407 | 47,961 | 12,909 | 3.43× | 12,832 |
| Language | lines | code | chars | tokens | ratio | cl100k |
|---|---|---|---|---|---|---|
| Python | 1,321 | 976 | 44,791 | 10,558 | 1.00× | 10,524 |
| TypeScript | 1,493 | 1,296 | 47,782 | 11,874 | 1.12× | 11,798 |
| C# | 1,360 | 1,156 | 53,574 | 12,180 | 1.15× | 12,016 |
| Java | 1,601 | 1,394 | 69,174 | 14,521 | 1.38× | 13,977 |
| PHP | 1,771 | 1,478 | 58,591 | 15,607 | 1.48× | 15,574 |
| Go | 2,338 | 2,099 | 60,217 | 16,518 | 1.56× | 16,456 |
| Rust | 2,147 | 1,951 | 69,348 | 17,560 | 1.66× | 17,534 |
| Zig | 1,995 | 1,787 | 74,498 | 19,418 | 1.84× | 19,330 |
| C++ | 2,467 | 2,185 | 85,800 | 21,254 | 2.01× | 21,155 |
| C | 3,245 | 2,892 | 109,025 | 29,532 | 2.80× | 29,321 |
Same data the other way round. This is the mechanism behind the shrink: the cheap build had the most room to grow into. Growth here is not good or bad, so nothing is colour-coded. A low multiple mean the build already carried a big fixed baseline at the small tier — C++ grow only 5.09× exactly because it start at 4,179 token for seven routes.
Click any header to sort.
| Language | small | mid | large | mid growth | large growth |
|---|---|---|---|---|---|
| C# | 1,100 | 4,054 | 12,180 | 3.69× | 11.07× |
| Rust | 1,637 | 6,484 | 17,560 | 3.96× | 10.73× |
| Python | 986 | 3,761 | 10,558 | 3.81× | 10.71× |
| Java | 1,489 | 5,094 | 14,521 | 3.42× | 9.75× |
| Go | 1,722 | 6,589 | 16,518 | 3.83× | 9.59× |
| Zig | 2,047 | 7,022 | 19,418 | 3.43× | 9.49× |
| TypeScript | 1,259 | 4,250 | 11,874 | 3.38× | 9.43× |
| PHP | 1,911 | 5,464 | 15,607 | 2.86× | 8.17× |
| C | 4,981 | 12,909 | 29,532 | 2.59× | 5.93× |
| C++ | 4,179 | 9,385 | 21,254 | 2.25× | 5.09× |
Millisecond from process spawn to the first good GET /health,
median across the three tiers. The harness measure its own detection cost on every run, so
the startup column have that floor removed instead of hiding it.
Click any header to sort.
| Language | small | mid | large | probe floor | startup |
|---|---|---|---|---|---|
| C | 63 | 81 | 59 | 18.5 | 47 ms |
| Go | 90 | 68 | 73 | 13.6 | 55 ms |
| Zig | 60 | 70 | 59 | 1.8 | 57 ms |
| C++ | 58 | 72 | 75 | 13.4 | 58 ms |
| Rust | 71 | 71 | 72 | 2.4 | 69 ms |
| PHP | 167 | 180 | 182 | 2.8 | 166 ms |
| TypeScript | 463 | 452 | 465 | 3.3 | 452 ms |
| C# | 962 | 722 | 455 | 10.5 | 712 ms |
| Python | 868 | 1,230 | 1,027 | 14.8 | 1,012 ms |
| Java | 6,218 | 5,294 | 4,976 | 19.4 | 5,275 ms |
Java take 112× longer than C to accept its first request. For a long-lived server that mean nothing. For anything that scale to zero, restart often, or run in a serverless container, it is the number that decide.
10,000 request, sequential, one at a time. Read p50. p99 and
max cluster on the 15.6 ms Windows timer tick — that is the client losing its scheduling
quantum, not the server. Do not rank on req/s: it derive from the mean, and
for a sub-millisecond server one stall cost the wall clock of ~50 normal request, so three
repeat run of Go gave 580, 1,095 and 1,145 while its p50 barely moved. Full variance study
in METHODOLOGY.md.
Click any header to sort.
| Language | p50 | p90 | mean | p99 | req/s |
|---|---|---|---|---|---|
| C | 0.166 | 0.234 | 0.279 | 0.7 | 3,454 |
| C++ | 0.200 | 0.265 | 0.378 | 9.8 | 2,561 |
| Zig | 0.211 | 0.276 | 0.378 | 3.1 | 2,562 |
| Rust | 0.251 | 0.320 | 0.522 | 12.4 | 1,868 |
| Go | 0.292 | 0.449 | 1.216 | 33.4 | 812 |
| C# | 0.404 | 0.675 | 1.457 | 34.3 | 679 |
| TypeScript | 0.426 | 0.589 | 0.969 | 17.5 | 1,014 |
| Java | 0.583 | 1.199 | 1.439 | 18.7 | 687 |
| Python | 1.256 | 3.190 | 3.321 | 49.6 | 299 |
| PHP | 1.362 | 22.102 | 6.506 | 55.2 | 153 |
| Language | p50 | p90 | mean | p99 | req/s |
|---|---|---|---|---|---|
| Zig | 0.192 | 0.257 | 0.315 | 10.8 | 3,065 |
| C++ | 0.214 | 0.287 | 0.391 | 11.3 | 2,481 |
| C | 0.216 | 0.287 | 0.423 | 11.7 | 2,280 |
| Rust | 0.264 | 0.331 | 0.434 | 11.5 | 2,240 |
| Go | 0.277 | 0.356 | 0.463 | 9.9 | 2,103 |
| C# | 0.380 | 0.513 | 0.631 | 10.5 | 1,551 |
| TypeScript | 0.428 | 0.571 | 0.773 | 13.4 | 1,269 |
| Java | 0.568 | 1.049 | 1.176 | 16.3 | 838 |
| Python | 1.397 | 2.170 | 2.232 | 13.0 | 445 |
| PHP | 1.452 | 22.883 | 6.825 | 58.8 | 146 |
| Language | p50 | p90 | mean | p99 | req/s |
|---|---|---|---|---|---|
| C++ | 0.218 | 0.280 | 0.379 | 11.2 | 2,543 |
| C | 0.240 | 0.306 | 0.466 | 11.6 | 2,084 |
| Zig | 0.254 | 0.317 | 0.487 | 12.0 | 1,986 |
| Go | 0.311 | 0.394 | 0.514 | 11.5 | 1,888 |
| Rust | 0.327 | 0.403 | 0.690 | 16.3 | 1,412 |
| TypeScript | 0.441 | 0.618 | 0.817 | 14.6 | 1,198 |
| C# | 0.444 | 0.645 | 1.157 | 18.7 | 850 |
| Java | 0.595 | 1.141 | 1.296 | 16.8 | 760 |
| Python | 1.621 | 4.360 | 3.743 | 50.4 | 266 |
| PHP | 8.636 | 37.014 | 16.105 | 70.0 | 62 |
10,000 request. Memory = resident set of the whole process tree, sampled every 20 ms. CPU = process-tree CPU second divided by request count, reported only from run of 1,000 or more, because the Windows CPU counter have about 15.6 ms resolution and a short run round to zero.
Click any header to sort.
| Language | CPU ms/req | idle RSS | peak RSS |
|---|---|---|---|
| C | 0.028 | 4.2 MB | 4.3 MB |
| C++ | 0.045 | 4.2 MB | 4.3 MB |
| Zig | 0.053 | 3.1 MB | 3.2 MB |
| Rust | 0.097 | 5.8 MB | 6.0 MB |
| Go | 0.169 | 8.3 MB | 15.2 MB |
| TypeScript | 0.297 | 65.2 MB | 71.5 MB |
| C# | 0.701 | 47.9 MB | 64.8 MB |
| PHP | 0.736 | 33.5 MB | 34.2 MB |
| Python | 1.254 | 48.3 MB | 48.5 MB |
| Java | 1.692 | 181.1 MB | 210.3 MB |
| Language | CPU ms/req | idle RSS | peak RSS |
|---|---|---|---|
| Zig | 0.053 | 3.3 MB | 3.4 MB |
| C | 0.053 | 4.2 MB | 4.3 MB |
| C++ | 0.075 | 5.1 MB | 5.2 MB |
| Rust | 0.105 | 6.0 MB | 6.3 MB |
| Go | 0.186 | 8.4 MB | 15.5 MB |
| TypeScript | 0.297 | 66.1 MB | 74.3 MB |
| C# | 0.490 | 48.5 MB | 63.9 MB |
| PHP | 0.901 | 34.3 MB | 34.7 MB |
| Python | 1.455 | 49.2 MB | 50.1 MB |
| Java | 1.478 | 185.5 MB | 204.6 MB |
| Language | CPU ms/req | idle RSS | peak RSS | RAM vs Zig |
|---|---|---|---|---|
| C | 0.059 | 4.2 MB | 4.7 MB | 1.3× |
| Zig | 0.069 | 3.3 MB | 4.2 MB | 1.0× |
| C++ | 0.070 | 5.2 MB | 6.0 MB | 1.6× |
| Rust | 0.150 | 6.2 MB | 7.5 MB | 1.9× |
| Go | 0.230 | 8.6 MB | 16.2 MB | 2.6× |
| TypeScript | 0.356 | 67.0 MB | 80.4 MB | 20.3× |
| C# | 0.653 | 50.9 MB | 66.6 MB | 15.4× |
| Java | 1.613 | 191.0 MB | 204.1 MB | 57.9× |
| Python | 1.764 | 50.0 MB | 52.4 MB | 15.2× |
| PHP | 5.097 | 34.5 MB | 36.7 MB | 10.5× |
p50 at each request count, large tier. Below 1.0 mean it got faster while running. Above 1.0 mean it degrade. This is where a warm-up effect or an accumulating-state problem show itself.
Click any header to sort.
| Language | 100 | 1,000 | 10,000 | drift | Reading |
|---|---|---|---|---|---|
| Java | 1.304 | 1.182 | 0.595 | 0.46× | JIT warm up, 2.2× faster by the end |
| C# | 0.499 | 0.548 | 0.444 | 0.89× | tiered JIT, same effect, smaller |
| C++ | 0.229 | 0.246 | 0.218 | 0.95× | flat |
| TypeScript | 0.458 | 0.464 | 0.441 | 0.96× | flat |
| C | 0.247 | 0.231 | 0.240 | 0.97× | flat |
| Rust | 0.332 | 0.336 | 0.327 | 0.99× | flat |
| Python | 1.598 | 1.464 | 1.621 | 1.01× | flat |
| Go | 0.294 | 0.293 | 0.311 | 1.06× | flat |
| Zig | 0.238 | 0.269 | 0.254 | 1.06× | flat |
| PHP | 2.360 | 2.926 | 8.636 | 3.66× | state accumulate on disk between request |
PHP is the only real degradation, and after the append-only store fix the cause
is no longer the audit trail — an isolated test of 2,000 audit-only write is
flat at 1.00×. What remain is 1,000 soft-deleted task row living in
store.json as domain state that every build in the tier also hold; PHP is just
the only one that has to re-serialize it, because a shared-nothing process cannot keep it in
memory. The absolute number improved a lot with the fix: 25.2 → 8.6 ms.
C and C++ cost the most token — and take place 1 and 2 on speed. Python cost the fewest token — and place 9. The two list are near mirror image. Nothing sit good at both end.
Click any header to sort.
| Language | token ratio | token rank | p50 ms | speed rank | shift | Caveman say |
|---|---|---|---|---|---|---|
| C++ | 2.01× | 10 | 0.218 | 1 | +9 | fastest, second most token |
| C | 2.80× | 11 | 0.240 | 2 | +9 | least CPU, fastest start, most token |
| Zig | 1.84× | 9 | 0.254 | 3 | +6 | least RAM at 3.3 MB, zero dependency |
| Go | 1.56× | 7 | 0.311 | 4 | +3 | good all round, most line of managed |
| Rust | 1.66× | 8 | 0.327 | 5 | +3 | fast, safe, many token |
| TypeScript | 1.12× | 2 | 0.441 | 6 | −4 | best mix, eat 67 MB |
| C# | 1.15× | 3 | 0.444 | 7 | −4 | dense code, mid speed |
| Java | 1.38× | 4 | 0.595 | 8 | −4 | JIT help later, 5 s start, 191 MB |
| PHP | 1.48× | 5 | 8.636 | 10 | −5 | zero dependency, but must re-serialize state |
| Python | 1.00× | 1 | 1.621 | 9 | −8 | fewest token, slow |
Shift = token rank minus speed rank. Plus mean faster than the token cost suggest.
At 7 routes C look terrible, 5.05×. At 34 routes it is 2.80×. Scaffolding written once then spread over every feature after. Most actionable result here: size a real backend from a toy comparison and you over-punish low-level by near double.
0.059 CPU ms per request on the big app. 86× less than PHP, 27× less than Java. Also the fastest cold start, 47 ms. And it cost the most token of anything measured.
3.3 MB idle against Java 191 MB — 57×. Standard library only, zero dependency,
all three tier. Cost: 1.84× Python token, and Zig 0.16 delete
std.net so almost no example exist for it.
OPcache off, framework rebuilt per request, store O(n). With a fresh store PHP answer in 1.66 ms, and with nothing at all in 0.874 ms — faster than C# or Python. What remain is the shared-nothing model, not the language.
No framework is faster and smaller at every tier: 4.5×, 4.3× and 2.0× faster p50, 5× less CPU, 15,607 token against 16,238, and no manifest. We measured PHP both way before dropping the framework one, which make this a direct read on framework cost with language and logic held constant.
p50 1.304 → 0.595 ms across the run, drift 0.46×, the only big improver. The bill come at start: 5,275 ms cold start, 191 MB RAM. Deployment shape decide whether that matter at all.
1.56× against 1.66×, after losing at mid. Go overhead is per-declaration, and the forced 4-module split gave it somewhere to spread that. Go still write the most line of any managed language, 2,338.
Beat Python on line count at small and mid — 134 vs 138, 451 vs 472. Then lose second place to TypeScript at large and become the fastest-growing build, 11.07×. A module split tax static typing at every boundary.
Java write 550 mid line against Rust 833 and still cost fewer token, because Rust line are narrow. Go write fewer character than Java, 23,400 against 23,652, yet cost 1,495 more token: Go encode 3.6 char per token against Java 4.6.
Token 2.80×. Cold start 112×. CPU 86×. RAM 57×. Throughput 41×. Speed 40×. Source size is the flattest axis in the whole study.
Every departure from a clean run, said out loud instead of smoothed over.
MAX_AUDIT is 2,048. The cycle write three audit entry, so the table fill
after about 680 cycle and further write answer 409. Count was 8,781
200, 477 201, 748 409. So C latency there look
slightly better than true, because a rejected write is cheap. Also a real finding: C is
the only build with a hard ceiling on accumulated state.perf-variance/.while samples < target spun forever. The probe now close, and the loop
raise on an error ceiling or on any cycle producing zero sample.No test case reach any of these. Recorded because each move the token count a
little, or because a language force the choice. Full list in
METHODOLOGY.md.
TaskItem, because Task
collide with System.Threading.Tasks.Task. And every build use
baseScore not base, because base is a C#
keyword.400; the
other eight ignore it. C and C++ would need a recursive value skipper; Zig inherit it from
the std.json default.POST
accept the key; the reference wire four route. Nine build follow the reference, C follow
the prose. No test case separate them — so this is a defect in our test, not in
any build.409 on
overflow. A real ceiling the other nine do not have.Response.OnStarting, Spring need a
ThreadLocal written during the handler, because both commit the response
while writing the body. Spring also rewrite a bare ETag into a quoted one
unless it is set on the raw servlet response.o200k_base and
cl100k_base, neither is Claude tokenizer, and no offline Claude tokenizer was
available. Absolute count will move elsewhere; the order hold across both encoder, which
is why the ratio column is the one to quote.