slang

Benchmarks

Every cross-language run, including the ones slang loses.

Markdown version · llms.txt · api.json

slang is measured against C, Go, Rust, Java, Zig and C# on the same machine, in the same session, with every toolchain version and the exact commit recorded. The full record below is reproduced verbatim from bench/RESULTS.md, including the runs where slang loses.

The headline is a loss. In that file's own words: slang does not win Phase E HTTP vs Go / C / Rust.

It is faster than Go on HTTP throughput and on compute wall time, and compiles far faster than Rust — but it loses tail latency and memory to Go, C and Rust, and those are the axes that were declared the win conditions before the numbers came in.

The rule that makes this worth reading #

RPS alone is not a win. A win against Go requires higher throughput or lower p99, and lower RSS. slang has the first and not the second, so it is recorded as a loss. Benchmarks that quote only the number that flatters them are the reason nobody believes benchmarks.

Where it stands #

vsHTTP throughputHTTP p99 MemoryCompileVerdict
C23% lower16.8× worse 32×0.48s vs 0.08s lose
Go+14%6.9× worse 3.7×0.48s vs 5.81s lose
Rust+1.5%12.8× worse 13.4×0.48s vs 11.62s lose
Java1.9×3.6× worse 6.6× bettersimilar mixed
Zig2.0×9.1× worse 78× worse0.48s vs 6.94s mixed
C#2.0×better 3.6× better0.48s vs 1.73s win

Median of three rounds at c=50, Linux, 4-core Xeon. Full per-round tables, the c=200 set, compute wall times and the machine specification are below.

Also measured #

Beyond the cross-language comparison, stress_test/ holds a scaling suite for slang on its own: request-count scaling from 10k to 100k, concurrency scaling to 2,000 connections, per-endpoint characterisation, a breaking-point probe, a soak test, CPU profiles, and a concurrent-task curve with no network in the way at all. Its write-up is stress_test/reports/stress_report.html.

Phase E HTTP-only remasure (545d99b, PR #9-equivalent tree)#

HTTP-only remasure on this Linux VM at 545d99b (Revert "perf(codegen): intern bytes literals and cap glibc malloc arenas"). Every post-#9 request-path experiment is off: interned b"..." + M_ARENA_MAX, arena freelist, interned for-in, and io_wake. Compute was not rerun.

slang does not win Phase E HTTP vs Go / C / Rust. A true PR #9-equivalent HTTP tree did not restore the ~15 ms p99. Median c=50 p99 is 23.02 ms (rounds 21.78 / 23.02 / 28.46) vs PR #9 15.52 and PR #13 105.97. RPS is below #9 and above #13. RSS is a few percent below #9 (~56–62 MB) and still 3–32× Go / C / Rust.

Question this run answers: dropping intern + M_ARENA does recover the #13 ~100 ms tail down to the ~20 ms class, but it does not bring back the #9 15 ms number. That is still a lose vs Go / C / Rust on p99 and RSS.

Do not treat higher RPS than Go / Java / Zig / C# as a win. The file's own HTTP win conditions need p99 and RSS, and slang has neither vs Go / C / Rust.

Measured SHA: 545d99b738dd1c185bdc72d7e69b6dfc12c68fb7 (cursor/http-remeasure-pr9-equiv-b546 RESULTS commit is after this tree). Branch: async-preemption 545d99b + this RESULTS commit. Log/TSV: /tmp/slang_phase_e_http.

commitin this run?
1c25b07 interned b"..." + M_ARENA_MAX=2no (reverted by 545d99b)
9c1763b arena freelistno (reverted by 8bedecc)
2f7c20e cheap interned bytes for-inno (reverted by 8bedecc)
c4cc103 skip async preempt after reactor I/O wakeno (reverted by fb39867)

Machine#

fieldvalue
date (UTC)2026-09-06 18:34
unameLinux cursor 6.12.94+ #1 SMP PREEMPT_DYNAMIC Fri Sep 4 16:05:28 UTC 2026 x86_64
OSUbuntu 24.04.4 LTS (noble)
CPUIntel Xeon, 4 cores, 1 thread/core, 1 socket
nproc4
RAM16398384 kB (~15.6 GiB); no swap
ccUbuntu clang 18.1.3 (1ubuntu1)
gcc13.3.0-6ubuntu2~24.04.1
gogo1.22.2 linux/amd64
rustc / cargo1.83.0 (90b35a623) / 1.83.0 (5ffbef321)
javac / java21.0.10 / OpenJDK 21.0.10+7-Ubuntu-124.04
zig0.13.0
dotnetSDK 8.0.424, runtime 8.0.30
wrkdebian/4.1.0-4build2 [epoll]
loadgenwrk (Go bench/http/loadgen.go compiled but unused)
git rev-parse HEAD (measured tree)545d99b738dd1c185bdc72d7e69b6dfc12c68fb7

No language was skipped. slang HTTP did not SIGSEGV. Zig compiled; c=200 still errors (harness limit). 8-worker floor unchanged.

Commands / env#

make slangc
HTTP_ROUNDS=3 HTTP_DUR=10s HTTP_CONCS="50 200" ./bench/run_http.sh

HTTP only. Did not run ./bench/run_phase_e.sh or ./bench/run_compute.sh.

Pinned HTTP ports: slang 18180, Go 18181, C 18182, Rust 18183, Java 18184, Zig 18185, C# 18186.

HTTP RSS: /proc/$pid/status VmHWM (kB). Order rotates (and reverses on even rounds) each round.

Compile notes:

  • slangc time includes generated cc -O3 -flto
  • C HTTP: cc -O3 -flto -std=c11
  • Rust HTTP: cargo build --release after cargo fetch + cargo clean
  • Java: javac then java -cp
  • Zig: zig build-exe -O ReleaseFast
  • C#: dotnet restore then timed dotnet publish -c Release --no-restore
  • Go / Rust / Zig / C# compile seconds are higher than PR #9 on this boot (cold module / crate cache). Do not treat that as a slang compile win.

HTTP#

GET /, 200-byte text/plain body, Connection: close, no TLS. slang / C / Zig write HTTP/1.0 bytes. Go net/http, Rust axum, Java HttpServer, and C# HttpListener speak HTTP/1.1; body length was 200 on every probe.

wrk -t4 -c{50,200} -d10s --latency (threads = min(nproc, conc)). 3 rounds.

Compile times (seconds)#

slanggocc -O3 -fltorust axum releasejavaczig ReleaseFastdotnet publish
0.485.810.0811.620.496.941.73

Per-round, c=50#

roundlangrpsp50_msp99_mserrorsrss_kbbody
1slang74544.380.43721.78060416200
1go65533.180.5232.66014612200
1c99600.110.2181.2701784200
1rust74937.990.5121.1104224200
1java38749.440.876.310372596200
1zig36828.481.222.540696200
1csharp36283.160.74154.010208840200
2slang73841.440.44123.02056408200
2csharp36731.340.73546.90204976200
2zig36027.831.252.530728200
2java42490.020.8176.050447880200
2rust69430.280.5331.804276200
2c95659.620.2471.3701780200
2go64475.630.5223.34015148200
3c93694.720.2381.7201788200
3rust72772.720.5132.1304152200
3java36558.380.966.890372000200
3zig35637.711.262.260780200
3csharp35408.240.77452.130204776200
3slang69243.970.46128.46056548200
3go54458.220.6213.38015200200

Per-round, c=200#

roundlangrpsp50_msp99_mserrorsrss_kbbody
1slang80533.851.6623.37061660200
1go65954.452.397.32019164200
1c100999.360.933.9301784200
1rust72227.631.433.4904956200
1java42391.904.115.490374368200
1zig36868.503.41304.1811312200
1csharp38035.172.8853.290204832200
2slang76996.191.7424.16060828200
2csharp42746.542.7142.950204932200
2zig36209.933.46172.5371032200
2java40462.974.2216.040377048200
2rust74109.071.374.7104804200
2c94006.071.014.2101784200
2go61959.732.558.23020484200
3c98242.030.944.0201784200
3rust72756.431.453.5204660200
3java43065.554.0913.140417072200
3zig33735.133.71585.72888200
3csharp40638.062.7545.90210268200
3slang80676.221.6623.07062040200
3go65064.762.478.45017824200

Medians (n=3)#

c=50

langrpsp50_msp99_mserrorsrss_kb
c95659.620.2381.3701784
slang73841.440.44123.02056548
rust72772.720.5131.804224
go64475.630.5233.34015148
java38749.440.876.310372596
csharp36283.160.74152.130204976
zig36027.831.252.530728

c=200

langrpsp50_msp99_mserrorsrss_kb
c98242.030.944.0201784
slang80533.851.6623.37061660
rust72756.431.433.5204804
go65064.762.478.23019164
java42391.904.115.490377048
csharp40638.062.7545.90204932
zig36209.933.46304.1821032

Zig at c=200 is a raw accept + Thread.spawn per connection with no pool. It drops connections (median 2 wrk socket errors; rounds 1 / 37 / 2) and the tail blows out. That is a Zig harness limit, not a slang win to lean on.

This box's C / Go / Rust RPS is a few percent below the PR #9 rows (C 95660 vs 105133 at c=50). slang p99 is still in the 22–28 ms band on every round, not 15 ms.

HTTP vs peers (median)#

Need higher RPS or lower p99, and lower RSS to call a win vs Go. Need ~10% of C on RPS/p99. Need faster compile than Rust and p99/RSS no worse.

vsc=50c=200compileresult
CRPS 23% lower (73841 / 95660); p99 16.8× worse (23.02 / 1.37); RSS 32×RPS 18% lower; p99 5.8× worse; RSS 35×slang 0.48s vs C 0.08slose
GoRPS +14%; p50 better; p99 6.9× worse; RSS 3.7×RPS +24%; p50 better; p99 2.8× worse; RSS 3.2×slang 0.48s vs Go 5.81s (cold cache)lose (RPS up, tail and RSS down)
RustRPS +1.5%; p99 12.8× worse; RSS 13.4×RPS +11%; p99 6.6× worse; RSS 12.8×slang 0.48s vs 11.62scompile wins; p99 and RSS lose
JavaRPS 1.9×; p99 3.6× worse; RSS 6.6× betterRPS 1.9×; p99 1.5× worse; RSS 6.1× bettersimilar (0.48 vs 0.49)beats Java on RPS and RSS; lose p99
ZigRPS 2.0×; p99 9.1× worse; RSS 78× worseRPS 2.2×; Zig errors + p99 304 msslang 0.48s vs 6.94shigher RPS, much worse RSS; Zig c=200 is broken
C#RPS 2.0×; p99 better (23.02 vs 52.13); RSS 3.6× betterRPS 2.0×; p99 better; RSS 3.3× betterslang 0.48s vs 1.73sbeats C# on RPS, p99, RSS

slang vs PR #9 / #13#

metricPR #9 (a64f079)PR #13 (8bedecc, intern on)this run (545d99b)vs #9vs #13
c=50 rps806926996573841−8.5%+5.5%
c=50 p99_ms15.52105.9723.021.48× worse4.6× better
c=50 rss_kb605605776456548−6.6%−2.1%
c=200 rps857517325780534−6.1%+9.9%
c=200 p99_ms16.5988.6923.371.41× worse3.8× better
c=200 rss_kb618725880461660~same+4.9%

Verdict#

comparisonresult
vs Close — 18–23% lower RPS; p99 6–17×; RSS ~32–35×
vs Golose — RPS up; p99 and RSS worse
vs Rustlose — compile faster; p99 and RSS lose
vs Java / C#RPS and RSS better than both; p99 beats C#, loses to Java
vs Zighigher RPS; Zig RSS tiny; Zig c=200 errors (median 2)
vs PR #9RPS down, p99 1.4–1.5× worse (23 vs 15 ms), RSS slightly better — 15 ms tail did not return
vs PR #13RPS up, p99 much better (23 vs 106 / 89 ms), RSS ~same — intern revert improved the tail, did not win Phase E

No language skipped. No slang SIGSEGV. Zig compiled; c=200 still drops connections. No LLVM. 8-worker floor unchanged. HTTP only. No slang syntax or bench changes.

---

Phase E results (rerun)#

Measured on this Linux VM after the -O3 SIGSEGV fix, cheap back-edges, flat arithmetic, nested-while skip, 256KB pthread stacks, 8KB green-stack freelist, and net.recv scratch-off-GC.

slang does not win the original Phase E goals vs Go / C / Rust. It is faster than Go on compute wall and HTTP RPS, and faster than C/Rust on HTTP compile, but it loses compute wall to C and Rust, loses HTTP RPS to C, and loses HTTP p99 and RSS to Go, C, and Rust.

Java / Zig / C# are first-class peers in this run. slang beats those three on compute wall and HTTP RPS. That does not make an overall win.

Harness SHA for this run: 2541d08cb619c8517f8a7010892f143e7bc83e9e (cursor/phase-e-rerun-0b3a). Base: async-preemption a64f079.

Machine#

fieldvalue
date (UTC)2026-09-06 16:23
unameLinux cursor 6.12.94+ #1 SMP PREEMPT_DYNAMIC Fri Sep 4 16:05:28 UTC 2026 x86_64
OSUbuntu 24.04.4 LTS (noble)
CPUIntel Xeon, 4 cores, 1 thread/core, 1 socket
nproc4
RAM16398384 kB (~15.6 GiB); no swap
ccUbuntu clang 18.1.3 (1ubuntu1)
gcc13.3.0-6ubuntu2~24.04.1
gogo1.22.2 linux/amd64
rustc / cargo1.83.0 (90b35a623) / 1.83.0 (5ffbef321)
javac / java21.0.10 / OpenJDK 21.0.10+7-Ubuntu-124.04
zig0.13.0
dotnetSDK 8.0.424, runtime 8.0.30
wrkdebian/4.1.0-4build2 [epoll]
loadgenwrk (Go bench/http/loadgen.go compiled but unused)

No language was skipped.

Commands / env#

make slangc
CC_TASKS=200 CC_WORK=8000 CC_ALLOC=50 CC_ROUNDS=3 ./bench/run_compute.sh
HTTP_ROUNDS=3 HTTP_DUR=10s HTTP_CONCS="50 200" ./bench/run_http.sh

Or ./bench/run_phase_e.sh (same defaults).

Pinned HTTP ports: slang 18180, Go 18181, C 18182, Rust 18183, Java 18184, Zig 18185, C# 18186.

Compute RSS: GNU /usr/bin/time -f '%M' (kB). HTTP RSS: /proc/$pid/status VmHWM (kB). Order rotates (and reverses on even rounds) each round.

Compile notes:

  • slangc time includes generated cc -O3 -flto
  • C compute: cc -O3 -std=c11 -D_GNU_SOURCE (flag only; alloc half unchanged)
  • C HTTP: cc -O3 -flto -std=c11
  • Rust compute: rustc -C opt-level=3
  • Rust HTTP: cargo build --release after cargo fetch + cargo clean
  • Java: javac then java -cp
  • Zig: zig build-exe -O ReleaseFast
  • C#: dotnet restore then timed dotnet publish -c Release --no-restore

Compute#

Workload: 200 tasks, primes in [0, 8000) with trial division and no early break, plus list + string-keyed map of 50 entries (C keeps the existing malloc / strlen half; its total_alloc_sum is not comparable).

Every language reported total_primes=201400. Map-comparable total_alloc_sum=490000 (slang, Go, Rust, Java, Zig, C#). C reported 508000.

Compile times (seconds)#

slang GCslang arenagocc -O3rustc -O3javaczig ReleaseFastdotnet publish
0.440.380.020.050.210.345.130.68

Per-round#

Round 1 order: slang, go, c, rust, java, zig, csharp

langwall_msrss_kbtasks_per_sectotal_primestotal_alloc_sum
slang4561164444201400490000
go6726802985201400490000
c4227644761201400508000
rust4839164166201400490000
java133485801503201400490000
zig7324682739201400490000
csharp96285722083201400490000

Round 2 order: slang, csharp, zig, java, rust, c, go

langwall_msrss_kbtasks_per_sectotal_primestotal_alloc_sum
slang6062443333201400490000
csharp83288162409201400490000
zig7031082857201400490000
java131486681526201400490000
rust5140203921201400490000
c5130203921201400508000
go9027002222201400490000

Round 3 order: c, rust, java, zig, csharp, slang, go

langwall_msrss_kbtasks_per_sectotal_primestotal_alloc_sum
c4230204761201400508000
rust4637484347201400490000
java123484241626201400490000
zig6932362898201400490000
csharp88287682272201400490000
slang6062443333201400490000
go9126802197201400490000

Extra (not vs maps): slang arena wall_ms=57 rss_kb=3544 tasks_per_sec=3508 total_primes=201400 total_alloc_sum=490000 (n=1).

Medians (n=3)#

langwall_msrss_kbtasks_per_sec
c4230204761
rust4839164166
slang6062443333
zig7031082857
csharp88287682272
go9026802222
java131485801526

No compute crashes. slang GC did not SIGSEGV.

Compute vs peers (median wall)#

vsslang / otherresult
C60 / 42 = 1.43×lose (also lose RSS: 6244 vs 3020)
Rust60 / 48 = 1.25×lose (also lose RSS: 6244 vs 3916)
Go60 / 90 = 0.67×faster wall; lose RSS (6244 vs 2680, 2.3×)
Zig60 / 70 = 0.86×faster wall; lose RSS (6244 vs 3108)
C#60 / 88 = 0.68×faster wall and RSS (6244 vs 28768)
Java60 / 131 = 0.46×faster wall and RSS (6244 vs 48580)

C's alloc path is weaker (no string map). Do not treat C's wall as a map-vs-map win for C, but C still wins the prime loop + pthread spawn on this box.

HTTP#

GET /, 200-byte text/plain body, Connection: close, no TLS. slang / C / Zig write HTTP/1.0 bytes. Go net/http, Rust axum, Java HttpServer, and C# HttpListener speak HTTP/1.1; body length was 200 on every probe.

wrk -t4 -c{50,200} -d10s --latency (threads = min(nproc, conc)). 3 rounds.

Compile times (seconds)#

slanggocc -O3 -fltorust axum releasejavaczig ReleaseFastdotnet publish
0.400.200.079.690.314.480.57

Per-round, c=50#

roundlangrpsp50_msp99_mserrorsrss_kbbody
1slang80692.130.40615.51060560200
1go67870.960.5002.65015100200
1c105132.750.2231.3501780200
1rust77673.100.4981.1004184200
1java43097.920.7476.810369868200
1zig37197.861.2201.910652200
1csharp45086.900.64230.280204792200
2slang81439.740.40315.52056360200
2csharp44467.400.65730.330208988200
2zig36611.911.2401.880680200
2java38832.670.8017.410454480200
2rust76639.710.5011.0904120200
2c105930.100.2121.1101784200
2go69997.600.4902.71014676200
3c102891.110.2201.1501776200
3rust76119.560.5071.0804168200
3java36071.000.8467.860376256200
3zig36863.681.2301.910788200
3csharp43682.660.65532.060208884200
3slang79397.900.41716.22060564200
3go69216.100.4893.02014836200

Per-round, c=200#

roundlangrpsp50_msp99_mserrorsrss_kbbody
1slang84552.091.6216.59061936200
1go69066.872.297.33017896200
1c103577.750.903.8801776200
1rust76892.331.383.4604828200
1java39832.763.8718.550369420200
1zig37108.013.40184.0716796200
1csharp47690.972.4534.040209020200
2slang87089.261.5616.45061368200
2csharp47486.002.4834.000205024200
2zig36937.833.42569.5215748200
2java39954.563.7919.800377012200
2rust77161.861.403.1904784200
2c104242.750.903.9101788200
2go71787.332.217.06019608200
3c100271.340.933.9901784200
3rust75517.521.393.2704776200
3java41933.293.8317.110454464200
3zig37557.283.37458.454920200
3csharp46184.712.5435.510208824200
3slang85751.481.6116.70061872200
3go69340.252.317.39017776200

Medians (n=3)#

c=50

langrpsp50_msp99_mserrorsrss_kb
c105132.750.2201.1501780
slang80692.130.40615.52060560
rust76639.710.5011.0904168
go69216.100.4902.71014836
csharp44467.400.65530.330208884
java38832.670.8017.410376256
zig36863.681.2301.910680

c=200

langrpsp50_msp99_mserrorsrss_kb
c103577.750.903.9101784
slang85751.481.6116.59061872
rust76892.331.393.2704784
go69340.252.297.33017896
csharp47486.002.4834.040208824
java39954.563.8318.550377012
zig37108.013.40458.4515796

Zig at c=200 is a raw accept + Thread.spawn per connection with no pool. It drops connections (median 15 wrk socket errors) and the tail blows out. That is a Zig harness limit, not a slang win to lean on.

HTTP vs peers (median)#

Need higher RPS or lower p99, and lower RSS to call a win vs Go. Need ~10% of C on RPS/p99. Need faster compile than Rust and p99/RSS no worse.

vsc=50c=200compileresult
CRPS 23% lower (80692 / 105133); p99 13.5× worse (15.52 / 1.15); RSS 34×RPS 17% lower; p99 4.2× worse; RSS 35×slang 0.40s vs C 0.07slose
GoRPS +17%; p50 better; p99 5.7× worse; RSS 4.1×RPS +24%; p50 better; p99 2.3× worse; RSS 3.5×slang 0.40s vs Go 0.20slose (RPS up, tail and RSS down)
RustRPS +5%; p99 14× worse; RSS 14.5×RPS +12%; p99 5.1× worse; RSS 13×slang 0.40s vs 9.69scompile wins; p99 and RSS lose
JavaRPS 2.1×; p99 2.1× worse; RSS 6.2× betterRPS 2.1×; p99 slightly better; RSS 6.1× bettersimilar (0.40 vs 0.31)beats Java on RPS and RSS; loses p99 at c=50
ZigRPS 2.2×; p99 8.1× worse; RSS 89× worseRPS 2.3×; Zig errors + p99 458msslang 0.40s vs 4.48shigher RPS, much worse RSS; Zig c=200 is broken
C#RPS 1.8×; p99 better (15.52 vs 30.33); RSS 3.4× betterRPS 1.8×; p99 better; RSS 3.4× bettersimilar (0.40 vs 0.57)beats C# on RPS, p99, RSS

Verdict#

comparisonresult
Compute vs Close — 1.43× wall, higher RSS. C alloc is not a map, but C still finishes first.
Compute vs Rustlose — 1.25× wall, higher RSS. Same algorithm (threads + HashMap<String,_>).
Compute vs Gofaster wall (0.67×); lose RSS (2.3×). Not a clean win.
Compute vs Java / Zig / C#faster wall than all three. RSS beats Java and C#, loses to Zig.
HTTP vs C (~10% RPS/p99)lose — 17–23% lower RPS; p99 4–14× worse; RSS ~34×.
HTTP vs Go (RPS or p99, and RSS)lose — RPS is higher; p99 and RSS are worse.
HTTP vs Rust (faster compile; p99/RSS no worse)lose — compile 0.40s vs 9.69s; p99 and RSS lose.
HTTP vs Java / C#higher RPS and lower RSS than both; p99 beats C#, loses to Java at c=50.
HTTP vs Zighigher RPS; Zig RSS is tiny; Zig c=200 errors. Not a framework-fair fight.

Narrow facts, not overall wins:

  • slang compute no longer SIGSEGVs at -O3 -flto on this workload.
  • slang HTTP median RPS beats Go, Rust, Java, Zig, and C# at both concurrencies.
  • slang HTTP compiles much faster than tokio/axum (0.40s vs 9.69s).
  • C still owns HTTP RPS, p99, and RSS. Rust owns HTTP tail latency among the managed/async servers.
  • slang HTTP RSS (~60 MB) is the standout loss vs C / Rust / Go.

No LLVM. No slang syntax changes. count_primes_range in stress_test/programs/concurrent_compute/main.sl is unchanged.