Some checks failed
Update All Top Ranking Issues / update_top_ranking_issues (push) Has been cancelled
Triage Project Sync (#84) / Sync triage project (push) Has been cancelled
release_nightly / notify_on_failure (push) Has been cancelled
release_nightly / check_style (push) Has been cancelled
release_nightly / run_tests_windows (push) Has been cancelled
release_nightly / clippy_windows (push) Has been cancelled
release_nightly / bundle_linux_aarch64 (push) Has been cancelled
release_nightly / bundle_linux_x86_64 (push) Has been cancelled
release_nightly / bundle_mac_aarch64 (push) Has been cancelled
release_nightly / bundle_mac_x86_64 (push) Has been cancelled
release_nightly / bundle_windows_aarch64 (push) Has been cancelled
release_nightly / bundle_windows_x86_64 (push) Has been cancelled
release_nightly / build_nix_linux_x86_64 (push) Has been cancelled
release_nightly / build_nix_mac_aarch64 (push) Has been cancelled
release_nightly / update_nightly_tag (push) Has been cancelled
Hotfix Review Monitor / check-hotfix-reviews (push) Has been cancelled
Stale PR Review Reminder / check-stale-prs (push) Has been cancelled
Update Weekly Top Ranking Issues / update_top_ranking_issues (push) Has been cancelled
Bump collab-staging Tag / update-collab-staging-tag (push) Has been cancelled
compliance_check / scheduled_compliance_check (push) Has been cancelled
Single-commit orphan branch: full zed-industries/zed @ 8c74db0 source tree with a 3-file patch applied (no upstream history). Patch (crates/gpui_linux/src/linux/wayland/): - serial.rs: add SerialKind::KeyboardEnter - client.rs: store wl_keyboard.enter serial; add latest_serial_of() - window.rs: activate() uses keyboard-enter serial (Mutter focus gate) Mutter honors window activation only when the token carries the keyboard- focus serial from wl_keyboard.enter; GPUI used a stale mouse-press serial. See docs/tray-window-focus-wayland.md in logiguard. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
341 lines
10 KiB
Rust
341 lines
10 KiB
Rust
use criterion::{BatchSize, BenchmarkId, Criterion, criterion_group, criterion_main};
|
|
use fuzzy::CharBag;
|
|
use std::sync::atomic::AtomicBool;
|
|
use util::{paths::PathStyle, rel_path::RelPath};
|
|
|
|
const DIRS: &[&str] = &[
|
|
"src",
|
|
"crates/gpui/src",
|
|
"crates/editor/src",
|
|
"crates/fuzzy_nucleo/src",
|
|
"crates/workspace/src",
|
|
"crates/project/src",
|
|
"crates/language/src",
|
|
"crates/terminal/src",
|
|
"crates/assistant/src",
|
|
"crates/theme/src",
|
|
"tests/integration",
|
|
"tests/unit",
|
|
"docs/architecture",
|
|
"scripts",
|
|
"assets/icons",
|
|
"assets/fonts",
|
|
"crates/git/src",
|
|
"crates/rpc/src",
|
|
"crates/settings/src",
|
|
"crates/diagnostics/src",
|
|
"crates/search/src",
|
|
"crates/collab/src",
|
|
"crates/db/src",
|
|
"crates/lsp/src",
|
|
];
|
|
|
|
const FILENAMES: &[&str] = &[
|
|
"parser.rs",
|
|
"main.rs",
|
|
"executor.rs",
|
|
"editor.rs",
|
|
"strings.rs",
|
|
"workspace.rs",
|
|
"project.rs",
|
|
"buffer.rs",
|
|
"colors.rs",
|
|
"panel.rs",
|
|
"renderer.rs",
|
|
"dispatcher.rs",
|
|
"matcher.rs",
|
|
"paths.rs",
|
|
"context.rs",
|
|
"toolbar.rs",
|
|
"statusbar.rs",
|
|
"keymap.rs",
|
|
"config.rs",
|
|
"settings.rs",
|
|
"diagnostics.rs",
|
|
"completion.rs",
|
|
"hover.rs",
|
|
"references.rs",
|
|
"inlay_hints.rs",
|
|
"git_blame.rs",
|
|
"terminal.rs",
|
|
"search.rs",
|
|
"replace.rs",
|
|
"outline.rs",
|
|
"breadcrumbs.rs",
|
|
"tab_bar.rs",
|
|
"Cargo.toml",
|
|
"README.md",
|
|
"build.sh",
|
|
"LICENSE",
|
|
"overview.md",
|
|
"string_helpers.rs",
|
|
"test_helpers.rs",
|
|
"fixtures.json",
|
|
"schema.sql",
|
|
];
|
|
|
|
const QUERY_WORDS: &[&str] = &[
|
|
"par",
|
|
"edi",
|
|
"buf",
|
|
"set",
|
|
"mat",
|
|
"con",
|
|
"ren",
|
|
"dis",
|
|
"sea",
|
|
"ter",
|
|
"col",
|
|
"hov",
|
|
"out",
|
|
"rep",
|
|
"key",
|
|
"too",
|
|
"pan",
|
|
"str",
|
|
"dia",
|
|
"com",
|
|
"executor",
|
|
"workspace",
|
|
"settings",
|
|
"terminal",
|
|
"breadcrumbs",
|
|
"git_blame",
|
|
"fixtures",
|
|
"schema",
|
|
"config",
|
|
"toolbar",
|
|
];
|
|
|
|
/// Deterministic query generation from QUERY_WORDS using a simple LCG.
|
|
/// Returns `count` queries of each arity: 1, 2, and 4 space-separated words.
|
|
fn generate_queries(count: usize) -> (Vec<String>, Vec<String>, Vec<String>) {
|
|
let mut state: u64 = 0xDEAD_BEEF;
|
|
let mut next = || -> usize {
|
|
// LCG: simple, fast, deterministic
|
|
state = state.wrapping_mul(6364136223846793005).wrapping_add(1);
|
|
(state >> 33) as usize
|
|
};
|
|
let mut n_word = |n: usize| -> Vec<String> {
|
|
(0..count)
|
|
.map(|_| {
|
|
(0..n)
|
|
.map(|_| QUERY_WORDS[next() % QUERY_WORDS.len()])
|
|
.collect::<Vec<_>>()
|
|
.join(" ")
|
|
})
|
|
.collect()
|
|
};
|
|
|
|
(n_word(1), n_word(2), n_word(4))
|
|
}
|
|
|
|
fn generate_candidates(count: usize) -> Vec<fuzzy_nucleo::StringMatchCandidate> {
|
|
(0..count)
|
|
.map(|id| {
|
|
let dir = DIRS[id % DIRS.len()];
|
|
let file = FILENAMES[id / DIRS.len() % FILENAMES.len()];
|
|
fuzzy_nucleo::StringMatchCandidate::new(id, &format!("{dir}/{file}"))
|
|
})
|
|
.collect()
|
|
}
|
|
|
|
fn to_fuzzy_candidates(
|
|
candidates: &[fuzzy_nucleo::StringMatchCandidate],
|
|
) -> Vec<fuzzy::StringMatchCandidate> {
|
|
candidates
|
|
.iter()
|
|
.map(|c| fuzzy::StringMatchCandidate::new(c.id, c.string.as_ref()))
|
|
.collect()
|
|
}
|
|
|
|
fn bench_string_matching(criterion: &mut Criterion) {
|
|
let cancel = AtomicBool::new(false);
|
|
|
|
let dispatcher = std::sync::Arc::new(gpui::TestDispatcher::new(0));
|
|
let background_executor = gpui::BackgroundExecutor::new(dispatcher.clone());
|
|
let foreground_executor = gpui::ForegroundExecutor::new(dispatcher);
|
|
|
|
let sizes = [100, 1000, 10_000];
|
|
let query_count = 200;
|
|
let (q1, q2, q4) = generate_queries(query_count);
|
|
|
|
for (label, queries) in [("1-word", &q1), ("2-word", &q2), ("4-word", &q4)] {
|
|
let mut group = criterion.benchmark_group(label);
|
|
for size in sizes {
|
|
let candidates = generate_candidates(size);
|
|
let fuzzy_candidates = to_fuzzy_candidates(&candidates);
|
|
|
|
let mut query_idx = 0usize;
|
|
group.bench_function(BenchmarkId::new("nucleo", size), |b| {
|
|
b.iter_batched(
|
|
|| {
|
|
let query = queries[query_idx % queries.len()].as_str();
|
|
query_idx += 1;
|
|
query
|
|
},
|
|
|query| {
|
|
foreground_executor.block_on(fuzzy_nucleo::match_strings_async(
|
|
&candidates,
|
|
query,
|
|
fuzzy_nucleo::Case::Ignore,
|
|
fuzzy_nucleo::LengthPenalty::On,
|
|
size,
|
|
&cancel,
|
|
background_executor.clone(),
|
|
))
|
|
},
|
|
BatchSize::SmallInput,
|
|
)
|
|
});
|
|
|
|
let mut query_idx = 0usize;
|
|
group.bench_function(BenchmarkId::new("fuzzy", size), |b| {
|
|
b.iter_batched(
|
|
|| {
|
|
let query = queries[query_idx % queries.len()].as_str();
|
|
query_idx += 1;
|
|
query
|
|
},
|
|
|query| {
|
|
foreground_executor.block_on(fuzzy::match_strings(
|
|
&fuzzy_candidates,
|
|
query,
|
|
false,
|
|
true,
|
|
size,
|
|
&cancel,
|
|
background_executor.clone(),
|
|
))
|
|
},
|
|
BatchSize::SmallInput,
|
|
)
|
|
});
|
|
}
|
|
group.finish();
|
|
}
|
|
}
|
|
|
|
fn generate_path_strings(count: usize) -> &'static [String] {
|
|
let paths: Box<[String]> = (0..count)
|
|
.map(|id| {
|
|
let dir = DIRS[id % DIRS.len()];
|
|
let file = FILENAMES[id / DIRS.len() % FILENAMES.len()];
|
|
format!("{dir}/{file}")
|
|
})
|
|
.collect();
|
|
Box::leak(paths)
|
|
}
|
|
|
|
fn generate_nucleo_path_candidates(
|
|
paths: &'static [String],
|
|
) -> Vec<fuzzy_nucleo::PathMatchCandidate<'static>> {
|
|
paths
|
|
.iter()
|
|
.map(|path| {
|
|
fuzzy_nucleo::PathMatchCandidate::new(RelPath::unix(path).unwrap(), false, None)
|
|
})
|
|
.collect()
|
|
}
|
|
|
|
fn generate_fuzzy_path_candidates(
|
|
paths: &'static [String],
|
|
) -> Vec<fuzzy::PathMatchCandidate<'static>> {
|
|
paths
|
|
.iter()
|
|
.map(|path| fuzzy::PathMatchCandidate {
|
|
is_dir: false,
|
|
path: RelPath::unix(path).unwrap(),
|
|
char_bag: CharBag::from(path.as_str()),
|
|
})
|
|
.collect()
|
|
}
|
|
|
|
fn capitalize_each_word(query: &str) -> String {
|
|
query
|
|
.split_whitespace()
|
|
.map(|w| {
|
|
let mut chars = w.chars();
|
|
match chars.next() {
|
|
Some(c) => c.to_ascii_uppercase().to_string() + chars.as_str(),
|
|
None => String::new(),
|
|
}
|
|
})
|
|
.collect::<Vec<_>>()
|
|
.join(" ")
|
|
}
|
|
|
|
fn bench_path_matching(criterion: &mut Criterion) {
|
|
let sizes = [100, 1000, 10_000];
|
|
let all_path_strings = sizes.map(generate_path_strings);
|
|
let query_count = 200;
|
|
let (q1, q2, q4) = generate_queries(query_count);
|
|
let q1_upper: Vec<String> = q1.iter().map(|q| capitalize_each_word(q)).collect();
|
|
let q2_upper: Vec<String> = q2.iter().map(|q| capitalize_each_word(q)).collect();
|
|
let q4_upper: Vec<String> = q4.iter().map(|q| capitalize_each_word(q)).collect();
|
|
|
|
for (label, queries, case) in [
|
|
("path/1-word", &q1, fuzzy_nucleo::Case::Ignore),
|
|
("path/2-word", &q2, fuzzy_nucleo::Case::Ignore),
|
|
("path/4-word", &q4, fuzzy_nucleo::Case::Ignore),
|
|
("path_smart/1-word", &q1_upper, fuzzy_nucleo::Case::Smart),
|
|
("path_smart/2-word", &q2_upper, fuzzy_nucleo::Case::Smart),
|
|
("path_smart/4-word", &q4_upper, fuzzy_nucleo::Case::Smart),
|
|
] {
|
|
let mut group = criterion.benchmark_group(label);
|
|
for (size_index, &size) in sizes.iter().enumerate() {
|
|
let path_strings = all_path_strings[size_index];
|
|
|
|
let mut query_idx = 0usize;
|
|
group.bench_function(BenchmarkId::new("nucleo", size), |b| {
|
|
b.iter_batched(
|
|
|| {
|
|
let query = queries[query_idx % queries.len()].as_str();
|
|
query_idx += 1;
|
|
(generate_nucleo_path_candidates(path_strings), query)
|
|
},
|
|
|(candidates, query)| {
|
|
fuzzy_nucleo::match_fixed_path_set(
|
|
candidates,
|
|
0,
|
|
None,
|
|
query,
|
|
case,
|
|
size,
|
|
PathStyle::Posix,
|
|
)
|
|
},
|
|
BatchSize::SmallInput,
|
|
)
|
|
});
|
|
|
|
let mut query_idx = 0usize;
|
|
group.bench_function(BenchmarkId::new("fuzzy", size), |b| {
|
|
b.iter_batched(
|
|
|| {
|
|
let query = queries[query_idx % queries.len()].as_str();
|
|
query_idx += 1;
|
|
(generate_fuzzy_path_candidates(path_strings), query)
|
|
},
|
|
|(candidates, query)| {
|
|
fuzzy::match_fixed_path_set(
|
|
candidates,
|
|
0,
|
|
None,
|
|
query,
|
|
false,
|
|
size,
|
|
PathStyle::Posix,
|
|
)
|
|
},
|
|
BatchSize::SmallInput,
|
|
)
|
|
});
|
|
}
|
|
group.finish();
|
|
}
|
|
}
|
|
|
|
criterion_group!(benches, bench_string_matching, bench_path_matching);
|
|
criterion_main!(benches);
|