From 2955c45a8c0d2e8f89030a7c82ae869e3f6cf755 Mon Sep 17 00:00:00 2001 From: hannah black Date: Wed, 10 Dec 2025 20:06:46 -0500 Subject: [PATCH 1/2] Small optimisations for MBE BindingsBuilder --- crates/mbe/src/expander/matcher.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/crates/mbe/src/expander/matcher.rs b/crates/mbe/src/expander/matcher.rs index 4da8b309f005..55ee5c13f9ca 100644 --- a/crates/mbe/src/expander/matcher.rs +++ b/crates/mbe/src/expander/matcher.rs @@ -159,9 +159,10 @@ struct BindingsBuilder<'a> { impl<'a> BindingsBuilder<'a> { fn alloc(&mut self) -> BindingsIdx { let idx = self.nodes.len(); - self.nodes.push(Vec::new()); + // allocate with a small default cap, reduce # of resizes + self.nodes.push(Vec::with_capacity(4)); let nidx = self.nested.len(); - self.nested.push(Vec::new()); + self.nested.push(Vec::with_capacity(4)); BindingsIdx(idx, nidx) } @@ -220,7 +221,9 @@ impl<'a> BindingsBuilder<'a> { fn build_inner(&self, link_nodes: &[LinkNode>>]) -> Bindings<'a> { let mut bindings = Bindings::default(); - let mut nodes = Vec::new(); + + // small optimisation: pre-allocate the space for collected nodes + let mut nodes = Vec::with_capacity(link_nodes.len()); self.collect_nodes(link_nodes, &mut nodes); for cmd in nodes { @@ -278,7 +281,9 @@ impl<'a> BindingsBuilder<'a> { fn collect_nested(&self, idx: usize, nested_idx: usize, nested: &mut Vec>) { let last = &self.nodes[idx]; - let mut nested_refs: Vec<&[_]> = Vec::new(); + + // small optimisation: pre-allocate nested_refs with a lower bound on capacity, to reduce realloc's + let mut nested_refs: Vec<&[_]> = Vec::with_capacity(self.nested[nested_idx].len() + 1); self.nested[nested_idx].iter().for_each(|it| match *it { LinkNode::Node(idx) => nested_refs.push(&self.nodes[idx]), LinkNode::Parent { idx, len } => self.collect_nested_ref(idx, len, &mut nested_refs), From b21e738e99d99216c0c2369b7f8705a8026be97f Mon Sep 17 00:00:00 2001 From: hannah black Date: Wed, 10 Dec 2025 20:21:49 -0500 Subject: [PATCH 2/2] Optimize mbe matcher allocations: performance issue #7857 --- crates/mbe/src/expander/matcher.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/mbe/src/expander/matcher.rs b/crates/mbe/src/expander/matcher.rs index 55ee5c13f9ca..4bce83c03d14 100644 --- a/crates/mbe/src/expander/matcher.rs +++ b/crates/mbe/src/expander/matcher.rs @@ -377,7 +377,7 @@ fn match_loop_inner<'t>( bindings_builder: &mut BindingsBuilder<'t>, cur_items: &mut SmallVec<[MatchState<'t>; 1]>, bb_items: &mut SmallVec<[MatchState<'t>; 1]>, - next_items: &mut Vec>, + next_items: &mut SmallVec<[MatchState<'t>; 4]>, eof_items: &mut SmallVec<[MatchState<'t>; 1]>, error_items: &mut SmallVec<[MatchState<'t>; 1]>, delim_span: tt::DelimSpan, @@ -650,7 +650,7 @@ fn match_loop<'t>( meta_result: None, }]; - let mut next_items = vec![]; + let mut next_items: SmallVec<[MatchState<'t>; 4]> = SmallVec::new(); loop { let mut bb_items = SmallVec::new();