Headless mux idle benchmark

On this page
  1. Headless mux idle benchmark
    1. Representative restored session
    2. Wakterm and upstream WezTerm

Headless mux idle benchmark#

The repeatable workload in scripts/bench_restored_mux.py measures the mux and its PTY children without a GUI client. It reports proportional set size (PSS), RSS, private memory, swap, process and thread counts, file descriptors, CPU time, context switches, faults, and read and write syscalls.

Representative restored session#

The restored fixture is based on the shape of the development host's active session on 2026-08-24, scaled from 12 to 20 harness workspaces:

  • 20 tabs, each with one harness-shaped PTY
  • 7 tabs with a second shell PTY, for 27 PTYs total
  • 8 parked tabs
  • one window and one workspace
  • deterministic sleep infinity payloads with empty scrollback

The fixture exercises persisted tab order, split trees, active panes, parked tabs, PTY creation, and the first periodic save. It does not launch an agent provider. Provider topology has its own benchmark because Codex memory would otherwise hide the mux result.

Run it with release binaries:

uv run --no-project scripts/bench_restored_mux.py \
  --setup restore \
  --server-bin target/release/wakterm-mux-server \
  --cli-bin target/release/wakterm \
  --tabs 20 --split-tabs 7 --parked-tabs 8 \
  --runs 3 --settle-seconds 10 --sample-seconds 65 \
  --output wakterm-restored.json

The 65-second sample intentionally crosses Wakterm's 60-second persistence interval. The sampler reads /proc and smaps_rollup; it does not poll the mux during the idle window.

Median of three runs on the host described below:

MetricResult
Restore 20 tabs and 27 PTYs149.0 ms
Mux PSS30.94 MiB
Mux plus 27 PTYs PSS34.44 MiB
Mux private memory30.89 MiB
Mux CPU time during sample1.05 ms
One-core CPU0.0016%
Read and write syscalls7 and 5
Voluntary context switches4
Major faults and swap0 and 0

Wakterm and upstream WezTerm#

The cross-project comparison uses the same cold spawn workload because Wakterm's v5 persisted layout is a fork-specific input. Each server gets 20 tabs with one sleeping PTY per tab. This compares headless mux and PTY steady state, not restoration behavior, terminal rendering, GPU memory, active output, or scrollback retention.

Measured on 2026-08-24:

  • AMD Ryzen 9 3950X, 32 logical CPUs, 31 GiB RAM
  • Fedora 44, Linux 7.1.9
  • rustc 1.95.0, release builds
  • Wakterm 6583a2e85
  • upstream WezTerm f93d90350
  • 10-second settle, 65-second sample, median of three runs
MetricWaktermWezTerm
Cold setup558.7 ms532.7 ms
Mux PSS29.62 MiB32.67 MiB
Mux plus 20 PTYs PSS32.15 MiB35.20 MiB
Mux private memory29.58 MiB32.63 MiB
CPU time during sample0.76 msbelow measurement resolution
One-core CPU0.0012%below measurement resolution
Mux threads9586
Mux file descriptors116110
Swap00

Wakterm used 3.05 MiB less PSS for both the mux and full process tree in this workload. Its cold setup took 26 ms longer. The measured Wakterm CPU includes the periodic persistence pass and is still about one thousandth of one CPU core.

Run the comparison with the same script and an upstream release build:

uv run --no-project scripts/bench_restored_mux.py \
  --flavor wakterm --setup spawn \
  --server-bin target/release/wakterm-mux-server \
  --cli-bin target/release/wakterm \
  --tabs 20 --runs 3 --settle-seconds 10 --sample-seconds 65

uv run --no-project scripts/bench_restored_mux.py \
  --flavor wezterm --setup spawn \
  --server-bin /path/to/wezterm-mux-server \
  --cli-bin /path/to/wezterm \
  --tabs 20 --runs 3 --settle-seconds 10 --sample-seconds 65

PSS is the primary memory number because it divides shared mappings among the processes that use them. Summed RSS is also retained in the JSON output, but it double-counts shared pages.

Edit this page