3.9 kB 55 lines
8f8ea000
⋯
bench/results/startup.md
download raw history
at main Markdown

knot-static startup bench (2026-11-08) #

base: b6c2803. rt: base + "answer cgi and ssh commands without a multi-thread runtime". harness: bench/startup (spawn -> first stdout byte, spawn -> wait4, rusage, max threads by a 100us sampler of /proc/pid/task or proc_pidinfo). fixture: scripts/startup-bench.sh (writes enabled, 40 accounts / ~80 keys in ssh-keys.json, meta repo via a partial init). cases: cgi_405 = fcgiwrap-style GET to /xrpc/com.atproto.repo.createRecord (config load, 405 in writable()); inflate_405 = KNOT_STATIC_INFLATE GET (405 in inflate::repo); keys_list = keys list --command ... (all lines); git_ssh_refuse = git-ssh --operator with SSH_ORIGINAL_COMMAND upload-pack of an unknown did (index rebuild, ERR pkt-line). outputs of base and rt are byte-identical for every case.

linux, chernobog (x86_64, 12 cpus, load ~2.2), times in ms, 3 interleaved rounds x 100 per bin (n=300) after warmup #

/run/current-system/sw/bin/true floor: 0.821 ms exit median

case bin first-byte med p95 mean exit med exit p95 cpu (u+s) med max threads minflt
cgi_405 base 2.204 2.623 2.216 2.426 3.044 3.515 13 499
cgi_405 rt 1.704 1.881 1.702 2.103 2.324 2.019 1 435
inflate_405 base 2.147 2.418 2.145 2.361 2.673 3.462 13 496
inflate_405 rt 1.716 2.282 1.790 2.111 2.760 2.034 1 433
keys_list base 2.452 3.198 2.482 2.662 3.507 3.761 13 553
keys_list rt 1.878 2.069 1.869 2.276 2.497 2.198 1 464
git_ssh_refuse base 3.332 3.717 3.299 3.558 4.037 4.639 13 616
git_ssh_refuse rt 2.811 3.211 2.817 3.318 3.794 3.223 1 550
clap reject (--version, exit 2) base - - - 2.164 2.427 2.862 13 491
clap reject (--version, exit 2) rt - - - 1.793 1.976 1.721 1 400

syscalls per run (strace -f -c, 3 runs):

case base syscalls rt syscalls
cgi_405 541-550 (12 clone3) 128 (0 clone3)
inflate_405 545-553 126
keys_list 551-557 119 (no futex, no epoll)
git_ssh_refuse 802-814 386

tracing ablation (also skip init_tracing on cgi + keys list unless RUST_LOG), linux n=300 interleaved: cgi_405 1.700 -> 1.656 ms med (-45 us), keys_list 1.891 -> 1.873 (-20 us). not applied: cgi emits tracing::error!/warn! (writes.rs "stored changes weren't published", spindle, firehose) that print_error's eprintln doesn't cover.

mac (caladon, arm64, 10 cpus), quiet run, n=300 interleaved #

case bin first-byte med p95 mean exit med exit p95 cpu (u+s) med max threads minflt
cgi_405 base 3.212 3.465 3.232 3.554 3.854 3.290 11 712
cgi_405 rt 3.111 3.342 3.126 3.381 3.636 2.830 1 675
inflate_405 base 3.207 3.452 3.230 3.547 3.827 3.288 11 709
inflate_405 rt 3.095 3.349 3.114 3.370 3.631 2.812 1 672
keys_list base 3.505 3.906 3.552 3.885 4.302 3.588 11 797
keys_list rt 3.285 3.500 3.294 3.563 3.796 2.998 1 725
git_ssh_refuse base 4.098 4.317 4.105 4.467 4.726 4.185 11 912
git_ssh_refuse rt 4.011 4.267 4.020 4.317 4.591 3.736 1 874
(a later mac rerun under load 17-22 from another session's tests was noise-dominated, ~11 ms everything; discarded.)
on the mac ~2.5 ms of the 3.1 ms is process/dyld startup (CoreFoundation/Security/SystemConfiguration frameworks), so the runtime change shows mostly as cpu and threads there.

what's left on linux #

rt cgi ~1.7 ms vs true 0.82 ms. strace -ttt puts the biggest remaining chunk in ld.so relocating the 32 MB PIE (the 741 KB RELRO mprotect comes after the longest gap), not in our code. a next lever would be link-level, not main().