https://gitlab.synchro.net/main/sbbs/-/commit/ab374f937dab91d23eed4d5e
Modified Files:
src/ssh/ssh-conn.c src/syncterm/Wren.adoc conn.c src/syncterm/scripts/sftp_app.wren sftp_queue.wren syncterm.wren src/syncterm/ssh.c term.c term.h wren_bind.c wren_host.c wren_host_internal.h
Log Message:
SFTP: pretend I know a thing or two about network performance
A grab bag of changes that took SFTP throughput from ~3 MB/s with the
serial chunk loop up to ~74 MB/s on a 10G localhost link against
OpenSSH, and gave the queue UI live throughput / ETA readouts.
Wren scripting / queue UI:
- Format.bytes / Format.duration / Timer.now bindings (wraps
byte_estimate_to_str, duration_estimate_to_str, xp_timer).
- SFTP queue display gets a sliding-window rate + ETA per active job.
- Hook limit bumped 8 → 256; with everything moving to Wren we were
already at 9 onKey hooks, and an all-Wren UI will only push it
higher.
doterm() main loop:
- Replaced the unconditional 1ms SLEEP with an xpevent
(doterm_wake_evt) so result-queue completions and conn buffer
arrivals wake the loop immediately. conn_buf_put and
wren_result_push post the wake; auto-reset event so a single
signal collapses to one drain pass.
SFTP queue (sftp_queue.wren):
- Per-job pipelining: PIPELINE_DEPTH chunk fibers per active job
with shared offset counter (JobCtx) and Wake-driven dispatcher
await. Out-of-order writes are fine because lf.writeBytes is
pwrite-style; resume-from-partial is dropped (holes are unsafe).
- Asymmetric EWMA for RTT and bandwidth (α=0.25 on bad direction,
α=0.0625 on good — react to congestion fast, recover cautiously).
- Adaptive chunk size targets bw × 75 ms keystroke budget, clamped
[4 KiB, 30 KiB].
- Adaptive pipeline depth = ceil(BDP / chunk) + 1, clamped [2, 32].
- Bootstraps to PIPELINE_DEPTH=8 / CHUNK=30720 until first samples
seed the estimators; reset on session start/stop.
DeuceSSH-side fixes (src/ssh/ssh-conn.c):
- maybe_replenish_window now routes WINDOW_ADJUST through
send_to_wa_slot (try-lock + coalescing slow path) instead of
blocking on tx_mtx via send_packet. Pre-credits local_window
under buf_mtx, mirroring the ZC-mode pattern.
SSH transport (src/syncterm/ssh.c):
- sftp_recv_thread buffer 4 KiB → 256 KiB (static — single-thread
accessor, never reentrant). Drains ~8 chunks per dssh_chan_read
instead of needing 8 syscalls per chunk.
- sftp_send no longer busy-spins when the server's window-to-us is
exhausted; parks on dssh_chan_poll(POLL_WRITE) until the next
inbound WINDOW_ADJUST broadcasts on poll_cnd.
- Conservative SO_SNDBUF cap to keep keystroke latency budget
intact under bulk SFTP load.
Co-Authored-By: Claude Opus 4.7 (1M context) <
noreply@anthropic.com>
---
■ Synchronet ■ Vertrauen ■ Home of Synchronet ■ [vert/cvs/bbs].synchro.net