Skip to content

Commit 39ceb01

Browse files
author
Foster Guo
committed
refactor: replace TinyVec with Vec for improved memory management in multiple modules
1 parent 019fe36 commit 39ceb01

7 files changed

Lines changed: 24 additions & 42 deletions

File tree

DESIGN.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@ For single-entry simple patterns, the automaton value encodes `rule_idx | (1 <<
331331
#### Bitmask vs Matrix
332332

333333
- **Bitmask** (≤64 segments, no repeated counts): each AND hit sets bit `offset` in `satisfied_mask` and decrements `remaining_and`. Reaching 0 → satisfied. NOT hits set `not_generation` immediately.
334-
- **Matrix** (>64 segments or repeated counts): a `TinyVec<[i32; 16]>` counter grid sized `[segments × variants]`. AND cells decrement; NOT cells increment. Threshold crossings tracked per-segment via `matrix_status`.
334+
- **Matrix** (>64 segments or repeated counts): a `Vec<i32>` counter grid sized `[segments × variants]`. AND cells decrement; NOT cells increment. Threshold crossings tracked per-segment via `matrix_status`.
335335

336336
```
337337
Rule parsed from pattern string
@@ -343,7 +343,7 @@ Rule parsed from pattern string
343343
≤64 segs, no repeats? ──► Bitmask (u64 + remaining_and)
344344
│ NO
345345
346-
Matrix (TinyVec counter grid)
346+
Matrix (Vec counter grid)
347347
```
348348

349349
---

matcher_rs/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ daachorse = "1.0.1"
3030
mimalloc = { version = "0.1.48", features = ["v3"] }
3131
serde = { version = "1.0.228", features = ["derive"], optional = true }
3232
serde_json = { version = "1.0", optional = true }
33-
tinyvec = { version = "1.11.0", features = ["alloc"] }
3433

3534
[dev-dependencies]
3635
divan = "0.1.21"

matcher_rs/src/process/graph.rs

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@
2424
2525
use std::collections::HashSet;
2626

27-
use tinyvec::TinyVec;
28-
2927
use crate::process::{
3028
process_type::ProcessType,
3129
step::{TransformStep, get_transform_step},
@@ -47,7 +45,7 @@ pub(crate) struct ProcessTypeBitNode {
4745
///
4846
/// Children represent the next transformation step that follows this one.
4947
/// Empty for leaf nodes.
50-
pub(crate) children: TinyVec<[usize; 4]>,
48+
pub(crate) children: Vec<usize>,
5149
/// Cached reference to the compiled [`TransformStep`] for this node's bit.
5250
///
5351
/// [`None`] only for the root node (which represents the raw input text and
@@ -67,13 +65,8 @@ pub(crate) struct ProcessTypeBitNode {
6765

6866
impl ProcessTypeBitNode {
6967
/// Returns the estimated heap memory in bytes used by the `children` vec.
70-
///
71-
/// Returns 0 when `children` fits in the inline `TinyVec` storage.
7268
pub(crate) fn heap_bytes(&self) -> usize {
73-
match &self.children {
74-
TinyVec::Heap(v) => v.capacity() * size_of::<usize>(),
75-
_ => 0,
76-
}
69+
self.children.capacity() * size_of::<usize>()
7770
}
7871
}
7972

@@ -115,7 +108,7 @@ pub(crate) fn build_process_type_tree(
115108
let mut process_type_tree = Vec::with_capacity(max_nodes);
116109
let mut root = ProcessTypeBitNode {
117110
process_type_bit: ProcessType::None,
118-
children: TinyVec::new(),
111+
children: Vec::new(),
119112
step: None,
120113
pt_index_mask: 0,
121114
};
@@ -144,7 +137,7 @@ pub(crate) fn build_process_type_tree(
144137
} else {
145138
let child = ProcessTypeBitNode {
146139
process_type_bit,
147-
children: TinyVec::new(),
140+
children: Vec::new(),
148141
step: Some(get_transform_step(process_type_bit)),
149142
pt_index_mask: pt_mask_bit,
150143
};

matcher_rs/src/simple_matcher/mod.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@
2121
2222
use std::{borrow::Cow, fmt, iter::FusedIterator};
2323

24-
use tinyvec::TinyVec;
25-
2624
use crate::process::graph::ProcessTypeBitNode;
2725

2826
mod build;
@@ -405,7 +403,7 @@ impl SimpleMatcher {
405403
if text.is_empty() {
406404
return SimpleMatchIter {
407405
rules: &self.rules,
408-
indices: TinyVec::new(),
406+
indices: Vec::new(),
409407
front: 0,
410408
back: 0,
411409
};
@@ -446,7 +444,7 @@ impl SimpleMatcher {
446444
#[must_use]
447445
pub struct SimpleMatchIter<'a> {
448446
rules: &'a RuleSet,
449-
indices: TinyVec<[usize; 16]>,
447+
indices: Vec<usize>,
450448
front: usize,
451449
back: usize,
452450
}

matcher_rs/src/simple_matcher/rule.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@
1212
1313
use std::{borrow::Cow, collections::HashMap};
1414

15-
use tinyvec::TinyVec;
16-
1715
use super::{
1816
SimpleResult,
1917
pattern::{PatternEntry, PatternKind},
@@ -258,8 +256,8 @@ impl RuleSet {
258256
}
259257

260258
/// Collects indices of satisfied touched rules for iterator construction.
261-
pub(super) fn collect_satisfied_indices(&self, ss: &ScanState<'_>) -> TinyVec<[usize; 16]> {
262-
let mut indices = TinyVec::new();
259+
pub(super) fn collect_satisfied_indices(&self, ss: &ScanState<'_>) -> Vec<usize> {
260+
let mut indices = Vec::new();
263261
for &rule_idx in ss.touched_indices() {
264262
if ss.rule_is_satisfied(rule_idx) {
265263
indices.push(rule_idx);

matcher_rs/src/simple_matcher/search.rs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,7 @@
2828
//! static is `#[thread_local]` (no cross-thread sharing) and the functions are
2929
//! not re-entrant. See [`SIMPLE_MATCH_STATE`] for the full safety argument.
3030
31-
use std::borrow::Cow;
32-
33-
use tinyvec::TinyVec;
31+
use std::{borrow::Cow, vec};
3432

3533
use super::{
3634
SimpleMatcher, SimpleResult,
@@ -301,15 +299,13 @@ impl SimpleMatcher {
301299
// density_flags[i] — non-ASCII byte density for arena index i.
302300
// density == 0.0 means pure ASCII (used for both engine dispatch and
303301
// transform correctness: is_noop_on_ascii_input, step.apply).
304-
let mut density_flags: TinyVec<[f32; 16]> = TinyVec::new();
302+
let mut density_flags: Vec<f32> = Vec::new();
305303
density_flags.push(root_density);
306304

307305
// Maps tree node index -> arena index for its text.
308-
let mut node_arena: TinyVec<[usize; 16]> = TinyVec::new();
309-
node_arena.resize(num_variants, 0);
306+
let mut node_arena: Vec<usize> = vec![0; num_variants];
310307
// Maps tree node index -> variant index used in ScanContext::text_index.
311-
let mut node_variant: TinyVec<[usize; 16]> = TinyVec::new();
312-
node_variant.resize(num_variants, 0);
308+
let mut node_variant: Vec<usize> = vec![0; num_variants];
313309
let mut variant_counter = 1usize;
314310
let mut stopped = false;
315311

matcher_rs/src/simple_matcher/state.rs

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@
2727
2828
use std::cell::UnsafeCell;
2929

30-
use tinyvec::TinyVec;
31-
3230
/// Per-rule mutable state reused across scans.
3331
///
3432
/// Each rule has one `WordState` slot in [`SimpleMatchState::word_states`],
@@ -96,19 +94,19 @@ pub(super) struct WordState {
9694
pub(super) struct SimpleMatchState {
9795
/// Per-rule state slots indexed by rule id.
9896
pub(super) word_states: Vec<WordState>,
99-
/// Per-variant counter matrix for complex rules (one `TinyVec` per rule
97+
/// Per-variant counter matrix for complex rules (one `Vec` per rule
10098
/// index).
10199
///
102100
/// `matrix[rule_idx][segment * num_variants + variant_idx]` holds the
103101
/// remaining count for that segment in that variant. Initialized lazily
104102
/// on first touch.
105-
pub(super) matrix: Vec<TinyVec<[i32; 16]>>,
106-
/// Per-segment completion flags for complex rules (one `TinyVec` per rule
103+
pub(super) matrix: Vec<Vec<i32>>,
104+
/// Per-segment completion flags for complex rules (one `Vec` per rule
107105
/// index).
108106
///
109107
/// `matrix_status[rule_idx][segment]` is 0 if the segment is still pending,
110108
/// 1 if it has been satisfied (AND) or triggered (NOT).
111-
pub(super) matrix_status: Vec<TinyVec<[u8; 16]>>,
109+
pub(super) matrix_status: Vec<Vec<u8>>,
112110
/// Rule indices touched during the current scan generation.
113111
///
114112
/// Cleared at the start of each scan in [`prepare`](Self::prepare). Used by
@@ -163,8 +161,8 @@ pub(super) struct ScanState<'a> {
163161
pub(super) word_states: &'a mut [WordState],
164162
pub(super) touched_indices: &'a mut Vec<usize>,
165163
pub(super) resolved_count: usize,
166-
pub(super) matrix: &'a mut [TinyVec<[i32; 16]>],
167-
pub(super) matrix_status: &'a mut [TinyVec<[u8; 16]>],
164+
pub(super) matrix: &'a mut [Vec<i32>],
165+
pub(super) matrix_status: &'a mut [Vec<u8>],
168166
pub(super) generation: u32,
169167
}
170168

@@ -333,8 +331,8 @@ impl SimpleMatchState {
333331

334332
if self.word_states.len() < size {
335333
self.word_states.resize(size, WordState::default());
336-
self.matrix.resize(size, TinyVec::new());
337-
self.matrix_status.resize(size, TinyVec::new());
334+
self.matrix.resize(size, Vec::new());
335+
self.matrix_status.resize(size, Vec::new());
338336
}
339337

340338
self.touched_indices.clear();
@@ -371,8 +369,8 @@ impl SimpleMatchState {
371369
#[cold]
372370
#[inline(never)]
373371
pub(super) fn init_matrix(
374-
flat_matrix: &mut TinyVec<[i32; 16]>,
375-
flat_status: &mut TinyVec<[u8; 16]>,
372+
flat_matrix: &mut Vec<i32>,
373+
flat_status: &mut Vec<u8>,
376374
segment_counts: &[i32],
377375
num_variants: usize,
378376
) {

0 commit comments

Comments
 (0)