# RQ3 Microbenchmark Results

Per-aspect overhead and 4-aspect composition cost at the tool-dispatch
join point. Reproduce with:

```
cargo bench -p aspect-std --bench agentic_aspects
```

## Environment

| Field | Value |
|---|---|
| Date | 2026-05-12 |
| CPU | Intel(R) Xeon(R) CPU E5-2690 v3 @ 2.60GHz |
| Kernel | Linux 5.15.0-173-generic x86_64 |
| Toolchain | rustc 1.96.0-nightly (38c0de8dc 2026-02-28) |
| Profile | `release` (criterion default) |
| Iterations | criterion defaults: 3 s warm-up, 5 s measurement, 100 samples |
| Commit | record at run time with `git rev-parse HEAD` |

## Results

Times are mean over 100 samples. 95% CIs from criterion's bootstrap.

### Baseline

| Bench | Mean | 95% CI |
|---|---:|---:|
| `dispatch_body` (raw target) | 4.1 ns | [4.1, 4.1] |
| `empty_chain` (harness only) | 29.9 ns | [29.9, 29.9] |

Harness floor: ~26 ns on top of a 4 ns target call.

### Single aspect at the tool-dispatch join point

| Aspect | Mean | 95% CI |
|---|---:|---:|
| `RateLimiter` | 394 ns | [394, 394] |
| `TokenBudget` | 554 ns | [554, 554] |
| `StructuredLogger` | 640 ns | [640, 641] |
| `ToolScopeSandbox` | 753 ns | [751, 754] |
| `ActionAuditTrail` | 1,292 ns | [744, 2,382] |

`ActionAuditTrail` has a wide CI because the bench appends to an
unbounded `Vec<AuditRecord>` across all iterations; allocator
behaviour dominates the tail. A production deployment would rotate
the trail (e.g. flush to disk every N records), which we measure
separately in the chain benches below.

### Composition (firing order: Sandbox → RateLimiter → [TokenBudget] → AuditTrail → Logger)

| Depth | Aspects | Mean | 95% CI |
|---:|---|---:|---:|
| 2 | Sandbox, RateLimiter | 1,086 ns | [1,086, 1,086] |
| 3 | + AuditTrail | 2,964 ns | [1,907, 5,074] |
| 4 | + Logger | 4,126 ns | [2,783, 6,799] |
| 5 | + TokenBudget (full set) | 4,916 ns | [3,491, 7,746] |

Chain depths ≥ 3 inherit the audit-trail allocator variance noted above.

### Short-circuit floor

| Scenario | Mean | 95% CI |
|---|---:|---:|
| Sandbox denies, 4-chain declared | 1,464 ns | [1,464, 1,465] |

Sandbox runs, returns `Err`, inner three aspects never fire. This is
the floor cost of a security denial through the full chain.

## Interpretation

- Full 5-aspect chain: **~4.9 µs** per tool dispatch — three orders of
  magnitude below typical LLM tool-call latency (1–100 ms), so the
  framework is not the bottleneck on the agent hot path.
- Per-aspect marginal cost: roughly 700–1,300 ns added per layer,
  depending on what the aspect does. `Box<dyn Aspect>` virtual
  dispatch + `Arc` cloning at each layer is the floor.
- Short-circuit path is **3.4× faster** than the full pass (1.5 µs
  vs. 4.9 µs at depth 5), confirming that outermost-first ordering
  for security aspects pays off when denials are common.

## Caveats

- Audit-trail bench grows unbounded; in production wire it to a
  bounded ring buffer or per-iteration drain. The 95% CI inflation
  is allocator noise, not aspect-dispatch overhead.
- Numbers are debug-asserts-off release. `RUSTFLAGS="-C
  target-cpu=native"` shaves another ~5–10% on this host.
- Single-host result. Cross-host variance not yet characterised.
