Skip to repository content

tenant.openagents/omega

No repository description is available.

OpenAgents Git authority 2026-07-28T03:13:12.213Z Public web read
NIP-34 coordinate30617:7649603503856e5148d571eac2766b288a8ff1e9e35d380337a1d2b0015b4f92:omega
MaintainersHidden in public view
References2 branches · 1 tag
Read-only clonegit clone https://openagents.com/git/tenant.openagents/omega.git
Browse files

match_benchmark.rs

345 lines · 10.3 KB · rust
1use criterion::{BatchSize, BenchmarkId, Criterion, criterion_group, criterion_main};
2use fuzzy::CharBag;
3use std::sync::atomic::AtomicBool;
4use util::{paths::PathStyle, rel_path::RelPath};
5
6const DIRS: &[&str] = &[
7    "src",
8    "crates/gpui/src",
9    "crates/editor/src",
10    "crates/fuzzy_nucleo/src",
11    "crates/workspace/src",
12    "crates/project/src",
13    "crates/language/src",
14    "crates/terminal/src",
15    "crates/assistant/src",
16    "crates/theme/src",
17    "tests/integration",
18    "tests/unit",
19    "docs/architecture",
20    "scripts",
21    "assets/icons",
22    "assets/fonts",
23    "crates/git/src",
24    "crates/rpc/src",
25    "crates/settings/src",
26    "crates/diagnostics/src",
27    "crates/search/src",
28    "crates/collab/src",
29    "crates/db/src",
30    "crates/lsp/src",
31];
32
33const FILENAMES: &[&str] = &[
34    "parser.rs",
35    "main.rs",
36    "executor.rs",
37    "editor.rs",
38    "strings.rs",
39    "workspace.rs",
40    "project.rs",
41    "buffer.rs",
42    "colors.rs",
43    "panel.rs",
44    "renderer.rs",
45    "dispatcher.rs",
46    "matcher.rs",
47    "paths.rs",
48    "context.rs",
49    "toolbar.rs",
50    "statusbar.rs",
51    "keymap.rs",
52    "config.rs",
53    "settings.rs",
54    "diagnostics.rs",
55    "completion.rs",
56    "hover.rs",
57    "references.rs",
58    "inlay_hints.rs",
59    "git_blame.rs",
60    "terminal.rs",
61    "search.rs",
62    "replace.rs",
63    "outline.rs",
64    "breadcrumbs.rs",
65    "tab_bar.rs",
66    "Cargo.toml",
67    "README.md",
68    "build.sh",
69    "LICENSE",
70    "overview.md",
71    "string_helpers.rs",
72    "test_helpers.rs",
73    "fixtures.json",
74    "schema.sql",
75];
76
77const QUERY_WORDS: &[&str] = &[
78    "par",
79    "edi",
80    "buf",
81    "set",
82    "mat",
83    "con",
84    "ren",
85    "dis",
86    "sea",
87    "ter",
88    "col",
89    "hov",
90    "out",
91    "rep",
92    "key",
93    "too",
94    "pan",
95    "str",
96    "dia",
97    "com",
98    "executor",
99    "workspace",
100    "settings",
101    "terminal",
102    "breadcrumbs",
103    "git_blame",
104    "fixtures",
105    "schema",
106    "config",
107    "toolbar",
108];
109
110/// Deterministic query generation from QUERY_WORDS using a simple LCG.
111/// Returns `count` queries of each arity: 1, 2, and 4 space-separated words.
112fn generate_queries(count: usize) -> (Vec<String>, Vec<String>, Vec<String>) {
113    let mut state: u64 = 0xDEAD_BEEF;
114    let mut next = || -> usize {
115        // LCG: simple, fast, deterministic
116        state = state.wrapping_mul(6364136223846793005).wrapping_add(1);
117        (state >> 33) as usize
118    };
119    let mut n_word = |n: usize| -> Vec<String> {
120        (0..count)
121            .map(|_| {
122                (0..n)
123                    .map(|_| QUERY_WORDS[next() % QUERY_WORDS.len()])
124                    .collect::<Vec<_>>()
125                    .join(" ")
126            })
127            .collect()
128    };
129
130    (n_word(1), n_word(2), n_word(4))
131}
132
133fn generate_candidates(count: usize) -> Vec<fuzzy_nucleo::StringMatchCandidate> {
134    (0..count)
135        .map(|id| {
136            let dir = DIRS[id % DIRS.len()];
137            let file = FILENAMES[id / DIRS.len() % FILENAMES.len()];
138            fuzzy_nucleo::StringMatchCandidate::new(id, &format!("{dir}/{file}"))
139        })
140        .collect()
141}
142
143fn to_fuzzy_candidates(
144    candidates: &[fuzzy_nucleo::StringMatchCandidate],
145) -> Vec<fuzzy::StringMatchCandidate> {
146    candidates
147        .iter()
148        .map(|c| fuzzy::StringMatchCandidate::new(c.id, c.string.as_ref()))
149        .collect()
150}
151
152fn bench_string_matching(criterion: &mut Criterion) {
153    let cancel = AtomicBool::new(false);
154
155    let dispatcher = std::sync::Arc::new(gpui::TestDispatcher::new(0));
156    let background_executor = gpui::BackgroundExecutor::new(dispatcher.clone());
157    let foreground_executor = gpui::ForegroundExecutor::new(dispatcher);
158
159    let sizes = [100, 1000, 10_000];
160    let query_count = 200;
161    let (q1, q2, q4) = generate_queries(query_count);
162
163    for (label, queries) in [("1-word", &q1), ("2-word", &q2), ("4-word", &q4)] {
164        let mut group = criterion.benchmark_group(label);
165        for size in sizes {
166            let candidates = generate_candidates(size);
167            let fuzzy_candidates = to_fuzzy_candidates(&candidates);
168
169            let mut query_idx = 0usize;
170            group.bench_function(BenchmarkId::new("nucleo", size), |b| {
171                b.iter_batched(
172                    || {
173                        let query = queries[query_idx % queries.len()].as_str();
174                        query_idx += 1;
175                        query
176                    },
177                    |query| {
178                        foreground_executor.block_on(fuzzy_nucleo::match_strings_async(
179                            &candidates,
180                            query,
181                            fuzzy_nucleo::Case::Ignore,
182                            fuzzy_nucleo::LengthPenalty::On,
183                            size,
184                            &cancel,
185                            background_executor.clone(),
186                        ))
187                    },
188                    BatchSize::SmallInput,
189                )
190            });
191
192            let mut query_idx = 0usize;
193            group.bench_function(BenchmarkId::new("fuzzy", size), |b| {
194                b.iter_batched(
195                    || {
196                        let query = queries[query_idx % queries.len()].as_str();
197                        query_idx += 1;
198                        query
199                    },
200                    |query| {
201                        foreground_executor.block_on(fuzzy::match_strings(
202                            &fuzzy_candidates,
203                            query,
204                            false,
205                            true,
206                            size,
207                            &cancel,
208                            background_executor.clone(),
209                        ))
210                    },
211                    BatchSize::SmallInput,
212                )
213            });
214        }
215        group.finish();
216    }
217}
218
219fn generate_path_strings(count: usize) -> &'static [String] {
220    let paths: Box<[String]> = (0..count)
221        .map(|id| {
222            let dir = DIRS[id % DIRS.len()];
223            let file = FILENAMES[id / DIRS.len() % FILENAMES.len()];
224            format!("{dir}/{file}")
225        })
226        .collect();
227    Box::leak(paths)
228}
229
230fn generate_nucleo_path_candidates(
231    paths: &'static [String],
232) -> Vec<fuzzy_nucleo::PathMatchCandidate<'static>> {
233    paths
234        .iter()
235        .map(|path| {
236            fuzzy_nucleo::PathMatchCandidate::new(
237                RelPath::from_unix_str(path).unwrap(),
238                false,
239                None,
240            )
241        })
242        .collect()
243}
244
245fn generate_fuzzy_path_candidates(
246    paths: &'static [String],
247) -> Vec<fuzzy::PathMatchCandidate<'static>> {
248    paths
249        .iter()
250        .map(|path| fuzzy::PathMatchCandidate {
251            is_dir: false,
252            path: RelPath::from_unix_str(path).unwrap(),
253            char_bag: CharBag::from(path.as_str()),
254        })
255        .collect()
256}
257
258fn capitalize_each_word(query: &str) -> String {
259    query
260        .split_whitespace()
261        .map(|w| {
262            let mut chars = w.chars();
263            match chars.next() {
264                Some(c) => c.to_ascii_uppercase().to_string() + chars.as_str(),
265                None => String::new(),
266            }
267        })
268        .collect::<Vec<_>>()
269        .join(" ")
270}
271
272fn bench_path_matching(criterion: &mut Criterion) {
273    let sizes = [100, 1000, 10_000];
274    let all_path_strings = sizes.map(generate_path_strings);
275    let query_count = 200;
276    let (q1, q2, q4) = generate_queries(query_count);
277    let q1_upper: Vec<String> = q1.iter().map(|q| capitalize_each_word(q)).collect();
278    let q2_upper: Vec<String> = q2.iter().map(|q| capitalize_each_word(q)).collect();
279    let q4_upper: Vec<String> = q4.iter().map(|q| capitalize_each_word(q)).collect();
280
281    for (label, queries, case) in [
282        ("path/1-word", &q1, fuzzy_nucleo::Case::Ignore),
283        ("path/2-word", &q2, fuzzy_nucleo::Case::Ignore),
284        ("path/4-word", &q4, fuzzy_nucleo::Case::Ignore),
285        ("path_smart/1-word", &q1_upper, fuzzy_nucleo::Case::Smart),
286        ("path_smart/2-word", &q2_upper, fuzzy_nucleo::Case::Smart),
287        ("path_smart/4-word", &q4_upper, fuzzy_nucleo::Case::Smart),
288    ] {
289        let mut group = criterion.benchmark_group(label);
290        for (size_index, &size) in sizes.iter().enumerate() {
291            let path_strings = all_path_strings[size_index];
292
293            let mut query_idx = 0usize;
294            group.bench_function(BenchmarkId::new("nucleo", size), |b| {
295                b.iter_batched(
296                    || {
297                        let query = queries[query_idx % queries.len()].as_str();
298                        query_idx += 1;
299                        (generate_nucleo_path_candidates(path_strings), query)
300                    },
301                    |(candidates, query)| {
302                        fuzzy_nucleo::match_fixed_path_set(
303                            candidates,
304                            0,
305                            None,
306                            query,
307                            case,
308                            size,
309                            PathStyle::Unix,
310                        )
311                    },
312                    BatchSize::SmallInput,
313                )
314            });
315
316            let mut query_idx = 0usize;
317            group.bench_function(BenchmarkId::new("fuzzy", size), |b| {
318                b.iter_batched(
319                    || {
320                        let query = queries[query_idx % queries.len()].as_str();
321                        query_idx += 1;
322                        (generate_fuzzy_path_candidates(path_strings), query)
323                    },
324                    |(candidates, query)| {
325                        fuzzy::match_fixed_path_set(
326                            candidates,
327                            0,
328                            None,
329                            query,
330                            false,
331                            size,
332                            PathStyle::Unix,
333                        )
334                    },
335                    BatchSize::SmallInput,
336                )
337            });
338        }
339        group.finish();
340    }
341}
342
343criterion_group!(benches, bench_string_matching, bench_path_matching);
344criterion_main!(benches);
345
Served at tenant.openagents/omega Member data and write actions are omitted.