From 1cdf5dff90db1c88acff95f0ed5993d9a8700794 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 25 Apr 2026 07:25:36 +0000 Subject: [PATCH] perf(sync): hash-set membership check in get_sync_status The deletion-detection loop in `get_sync_status` scanned `local_files` linearly for every tracked path in `sync_state.files`, making the cost quadratic in the file count. The earlier "pending change" loop just above already does the inverse direction via `sync_state.files.get` (O(1)). Build a `HashSet<&str>` of local paths once and check it the same way to make the function O(n). This is called by the GUI status indicator, so the win shows up as soon as a workspace tracks more than a handful of files. --- crates/onyx-core/src/sync.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/crates/onyx-core/src/sync.rs b/crates/onyx-core/src/sync.rs index a21cf9d..c97f0c6 100644 --- a/crates/onyx-core/src/sync.rs +++ b/crates/onyx-core/src/sync.rs @@ -914,9 +914,15 @@ pub fn get_sync_status(workspace_path: &Path) -> Result { } } - // Count files in base that are now missing locally (deleted) + // Count files in base that are now missing locally (deleted). + // Build a set of local paths once so the membership check is O(1) per + // tracked file instead of scanning local_files linearly each time. + let local_paths: std::collections::HashSet<&str> = local_files + .iter() + .map(|f| f.path.as_str()) + .collect(); for path in sync_state.files.keys() { - if !local_files.iter().any(|f| f.path == *path) { + if !local_paths.contains(path.as_str()) { pending_changes += 1; } }