Shipping whyslow v1
The problem
Every Linux dev has hit “my program is slow” and reached for strace,
perf, or py-spy — but each tool sees one layer. None of them tell you
why across layers. You end up manually cross-referencing three terminal
windows and timestamps by hand.
What I built
whyslow — a CLI that watches sched_switch, futex, and block I/O events
via eBPF and stitches them into a single causal chain:
$ sudo whyslow run -- ./my-slow-program
14:32:07.001 — tid 4821 blocked 412ms on futex 0x7f2a3c001000
← woken by tid 4809
← tid 4809 blocked 380ms on block I/O (dev nvme0n1p2, sector 88213)
No manual correlation. It finds the root cause and walks you back to it.
Stack
- Rust,
ayafor pure-Rust eBPF (no libbpf/C toolchain needed) - Ring buffer for low-overhead event collection — can’t perturb the thing
you’re measuring - Interval tree + happens-before edge inference for the causal graph
- Workspace:
whyslow-cli,whyslow-ebpf,whyslow-common
Scope for v1
- x86_64 + aarch64 Linux, kernel 5.8+
- Three event sources: sched_switch, futex, block I/O
- No stack symbolication yet — tid/pid/comm only
- Needs root or
CAP_BPF— no way around that, eBPF is privileged
Kept scope narrow on purpose: three event sources done correctly beats
eight done half right. Validated against a synthetic program that
deliberately causes futex contention + a disk stall, so there’s ground
truth to check the causal chain against, not just vibes.
Distribution
curl -sSf .../install.sh | sh- Homebrew tap, APT repo, pip wrapper — see
DISTRIBUTION.md - crates.io publish still pending —
cargo installworks via--gitfor now
What’s next
- Stack symbolication (native + interpreted languages)
- More event sources without losing causal-chain accuracy
- Actual crates.io publish so
cargo install whyslowjust works
Comments 1
hey man please dont use ai for devlogs :)
Sign in to join the conversation.