chore(release): 0.4.1

Bump workspace version 0.4.0 → 0.4.1.

Patch release: dispatch hot-path performance only. No public API
changes; every chart that compiled against 0.4.0 compiles unchanged
and behaves identically. CHANGELOG.md captures the per-pass writeup
under the 0.4.1 heading.

Headlines (deepest dispatch in the bench suite):
  h8_cross_tree     -82% instructions / -72% cycles  vs pre_lca_fix
  bubble_top        -22% instructions /  -6% cycles  vs handler walk
  terminate_event   -22% instructions / -23% cycles  vs PARENT walk

The runtime LCA helper, is_up_transition, the per-call heapless::Vec
ancestry build, the runtime PARENT bubble walk, and (on timer-free
charts) the entire TimerTable machinery are all gone. Callgrind
reports the entire HSM machinery as a single inlined `step` symbol.

Bench suite expanded from 7 to 13 benches: bubble_leaf/mid/top
quantify handler resolution at varying ancestor depths,
timer_fire_dispatch covers the only path that exercises pop_expired's
non-empty branch, terminate_event covers do_terminate, and
bubble_cross_tree covers the realistic HSM worst case (deep bubble +
deep cross-tree transition).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
swaitsandClaude Opus 4.7 committed 2026-04-28 19:11:29 -06:00
1 parent dc97419161
commit 2e55484080
6 files changed
+60 -50

No files matched your search

+4 -2
View File
@@ -329,13 +329,15 @@ fn compute_terminate_paths(states: &[StateIr]) -> (Vec<u16>, Vec<(u16, u16)>) {
fn compute_event_dispatch(ir: &Ir) -> Vec<(u16, Vec<u16>, Option<u16>)> {
use std::collections::BTreeMap;
/// `event_id → (action_ids, transition_target)` aggregation for one state.
type StateHandlers = BTreeMap<u16, (Vec<u16>, Option<u16>)>;
let n_states = ir.states.len();
let n_events = ir.event_variants.len();
// Per-state, per-event handler resolution. Mirrors the aggregation in
// `state_handler_arms` (sort by decl_index, group by trigger).
let mut per_state: Vec<BTreeMap<u16, (Vec<u16>, Option<u16>)>> =
vec![BTreeMap::new(); n_states];
let mut per_state: Vec<StateHandlers> = vec![StateHandlers::new(); n_states];
for (sid, state) in ir.states.iter().enumerate() {
let mut handlers = state.handlers.iter().collect::<Vec<_>>();
handlers.sort_by_key(|h| h.decl_index);