Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .jules/bolt.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,7 @@
## 2025-11-05 - [Replace HashMap Allocation with Flat Vec for Block Lookup]
**Learning:** In the `flatten_blocks` function within `orch8-engine/src/evaluator.rs`, allocating a `HashMap<&BlockId, &BlockDefinition>` to map execution blocks introduces significant hashing and memory allocation overhead on the evaluation hot path, which is called every tick. Since the tree size is typically bounded and small, building a `Vec` and sorting it by `BlockId` allows for O(log N) lookups via `.binary_search_by_key()`, completely avoiding `HashMap` overhead.
**Action:** In execution hot paths where a lookup map is created from a slice on every iteration, always prefer a flat `Vec` initialized with `Vec::with_capacity()`, sorted by key, and queried via `.binary_search_by_key()` over a `HashMap` to eliminate hashing and heap allocation costs.

## 2025-11-06 - [Optimize children_of using Vec::with_capacity]
**Learning:** In `orch8-engine/src/evaluator.rs`, the `children_of` function is called heavily on the hot path for all execution node evaluations. It previously chained `.filter(...).collect()` on the execution tree slice. Because `.filter()` creates an iterator of unknown size, `.collect()` causes the resulting `Vec` to allocate and potentially reallocate multiple times as elements are found.
**Action:** Replace `.filter(...).collect()` chains in hot paths with a manual `for` loop pushing to a `Vec` instantiated with `Vec::with_capacity(N)` when a reasonable small bound (like 8 for most child node scenarios) is known. This significantly eliminates redundant iterator and allocator overhead.
19 changes: 13 additions & 6 deletions orch8-engine/src/evaluator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1250,12 +1250,19 @@ pub fn children_of(
parent_id: ExecutionNodeId,
branch_index: Option<i16>,
) -> Vec<&ExecutionNode> {
tree.iter()
.filter(|n| {
n.parent_id == Some(parent_id)
&& (branch_index.is_none() || n.branch_index == branch_index)
})
.collect()
// ⚡ Bolt: Replace `.filter().collect()` with a manual loop and `Vec::with_capacity`
// to avoid multiple reallocation overheads when collecting an unknown-sized iterator.
// Most nodes have a small number of direct children, so preallocating a small capacity
// is highly efficient.
let mut children = Vec::with_capacity(8);
for n in tree {
if n.parent_id == Some(parent_id)
&& (branch_index.is_none() || n.branch_index == branch_index)
{
children.push(n);
}
}
children
}

/// Check if all nodes in a set are in a terminal state.
Expand Down
Loading