feat(daemon): app daemon-request latency probe (debug.daemon_requests)

LA
21h ago
+282-6

Summary

Austin's 80-agent day (#27698) showed window-state saves that got "no reply within 2.0 s". The P-AUSTIN target for a fix is an app request p99 under 50 ms at 80 agents. Until now the app recorded no latency for its own requests to the daemon; only the time-outs show in its log. This PR adds a probe for that latency. The Austin's-day harness (#28077) reads it.

  • What it records: DaemonRequestLatency is a fixed log-linear histogram: [0, 64 µs], then 4 buckets per power of two up to about 67 s, then an overflow bucket. It also counts errors and time-outs and keeps the maximum.
    • Each counter is a relaxed atomic. Recording takes no lock and allocates nothing per request. Its marks are // perf-hot: 1us daemon-request and a new daemon-request entry in perf-hot-benches.json.
  • Where it records: LineTransport.request records each request from send to reply or failure. The outcome is reply, error, or time-out (DaemonError.timedOut).
  • Who owns the probe: the local DaemonService makes one probe and passes it in through DaemonConnectionConfiguration.requestLatency. The prestart connection and every later connection record into that same probe. There is no static singleton.
  • How you read it: debug.daemon_requests, answered off the main actor. It returns the bounds, the counts, errors, time-outs, the maximum, and p50/p95/p99. A reader diffs two reads to get a window.
    • The probe sits in RequestLatencySlot, a nonisolated Sendable class whose state is a Mutex. The debug closure captures that class, not self.
  • Debug and bench builds only. Release makes no probe and registers no debug.* method. A debug path that works in Release would be a new socket surface, which needs its own policy review. The harness runs bench builds, so this case does not need one (lead decision, 2026-10-30).

Testing

  • Red: DaemonRequestLatencyTests at 005bb70d92f (test only), step 202b74b54c46c9b5694a34ae on aws-m4pro-2: it fails. The test target does not compile: cannot find 'DaemonRequestLatency' in scope. That is the right reason: the type comes with the next commit.
  • Green: DaemonRequestLatencyTests at 4a78243dee2, step eea4a580abef5f23fe3f3e18 on cmux14: 3 of 3 tests passed.
  • Compile: cmux-ci compile-check --app --package CmuxNext --recipe-version 2 at 4a78243dee2, job d69b50218c13120ff0fba9f7: pass. Two earlier compiles failed and were fixed:
    • b5a19cfe: the closure captured a noncopyable Mutex;
    • b65f309e: the slot was main-actor isolated by the target's default.
  • Prepush gate: clean.

Observed / Not run

  • Observed: the red and green suite runs, the compile-check, and the prepush gate.
  • Not run:
    • The probe in a live app under load. The first Austin's-day run of a build with this probe will show its numbers.
    • The probe's own cost (the daemon-request perf-hot bench). It has not run.

Changelog

none

Proof

No capture: no visible UI changes; this is a Debug and bench diagnostic.