feat(causal): instrument the request hot path — five sites and a progress point

RFC 007 causal-site coverage for the Phase 2 bench (and any downstream
profiling): parse (head parsing attempts in read_head), router (dispatch
matching only — the winning handler and the next fall-through run outside
the guard, so the site measures dispatch, not what it dispatches to;
call() restructured match-then-dispatch for that, semantics preserved
incl. first-path+method-match-wins and the 405 two-pass), pipeline (the
plug chain inside catch_unwind; nested sites like router take over
attribution during their span, so this reads as chain overhead + handler
code outside inner sites), serialize (response head+bytes-body
serialisation; chunked stream framing is not covered — it interleaves
with writes in pump_stream and the bench doesn't stream), and
socket-write (all of write_all, writability parks included: a park
inside a site is exactly what the park-gated resume credit attributes).

progress!("responses") fires once per response fully on the wire, at
both completion points (the common path and the HTTP/1.0 EOF-stream
early return).

Site guards are #[cfg(feature = "smarm-causal")]-gated: the macros are
no-ops featureless, but binding the unit expansion would trip clippy's
let_unit_value. progress! is bare — its featureless expansion is an
empty block, free and lint-clean. Featureless build byte-behavior is
unchanged; both configs clippy-clean, full suite green both ways.
This commit is contained in:
Claude
2026-07-13 08:30:53 +00:00
parent 072ee126f9
commit ecaddc579a
2 changed files with 42 additions and 8 deletions
+19 -6
View File
@@ -135,16 +135,29 @@ impl Plug for Router {
// path matches but a same-path-different-method does, return 405.
// Otherwise pass through to `next` so outer pipelines can layer a
// 404 handler (or skip and let the connection actor emit a default).
//
// Matching runs under the `router` causal site (RFC 007); the
// winning handler and the `next` fall-through run outside it, so
// the site measures dispatch, not what it dispatches to.
let mut path_seen = false;
for route in &self.routes {
if let Some(params) = route.pattern.match_path(&conn.path) {
if route.method == conn.method {
let conn = conn.put_params(params);
return route.handler.call(conn, next);
let mut hit = None;
{
#[cfg(feature = "smarm-causal")]
let _g = smarm::causal_site!("router");
for (i, route) in self.routes.iter().enumerate() {
if let Some(params) = route.pattern.match_path(&conn.path) {
if route.method == conn.method {
hit = Some((i, params));
break;
}
path_seen = true;
}
path_seen = true;
}
}
if let Some((i, params)) = hit {
let conn = conn.put_params(params);
return self.routes[i].handler.call(conn, next);
}
if path_seen {
// Path is known, method isn't — RFC 7231 §6.5.5.
conn.put_status(405)