From 78658778a28fe9bfac2de9caddcdad0eb4ea1cd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20Raz=20Guzm=C3=A1n=20Macedo?= Date: Mon, 8 Jun 2026 13:47:30 -0600 Subject: [PATCH] Use unstable sorts if deduplicating (#58751) # Impact Recent Project picker, `find all references`, the sidebar's `rebuild_contents` might get a slight speed boost. # Reasoning Unstable sort variants https://doc.rust-lang.org/stable/std/primitive.slice.html#method.sort_unstable are non-allocating but potentially destructive. Since we're deduplicating elements anyways, use the unstable variant. This call will use ipnsort https://github.com/Voultapher/sort-research-rs/blob/main/writeup/unreasonable/text.md#various-generic-algorithms I expect the speedups to be at least 30%, though it's highly input dependent. Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Release Notes: - N/A --- crates/editor/src/navigation.rs | 6 +++--- crates/extension/src/extension_manifest.rs | 4 ++-- crates/gpui/src/text_system.rs | 2 +- crates/gpui_wgpu/src/cosmic_text_system.rs | 2 +- crates/language/src/buffer.rs | 2 +- crates/project/src/bookmark_store.rs | 2 +- crates/project/src/lsp_store.rs | 2 +- crates/recent_projects/src/recent_projects.rs | 4 ++-- crates/sidebar/src/sidebar.rs | 2 +- 9 files changed, 13 insertions(+), 13 deletions(-) diff --git a/crates/editor/src/navigation.rs b/crates/editor/src/navigation.rs index a8fc021b33c..051b7f0ab42 100644 --- a/crates/editor/src/navigation.rs +++ b/crates/editor/src/navigation.rs @@ -1313,12 +1313,12 @@ impl Editor { return anyhow::Ok(Navigated::No); } for ranges in locations.values_mut() { - ranges.sort_by_key(|range| (range.start, Reverse(range.end))); + ranges.sort_unstable_by_key(|range| (range.start, Reverse(range.end))); ranges.dedup(); } let mut num_locations = 0; for ranges in locations.values_mut() { - ranges.sort_by_key(|range| (range.start, Reverse(range.end))); + ranges.sort_unstable_by_key(|range| (range.start, Reverse(range.end))); ranges.dedup(); num_locations += ranges.len(); } @@ -1631,7 +1631,7 @@ impl Editor { })?; let mut num_locations = 0; for ranges in locations.values_mut() { - ranges.sort_by_key(|range| (range.start, Reverse(range.end))); + ranges.sort_unstable_by_key(|range| (range.start, Reverse(range.end))); ranges.dedup(); // Merge overlapping or contained ranges. After sorting by // (start, Reverse(end)), we can merge in a single pass: diff --git a/crates/extension/src/extension_manifest.rs b/crates/extension/src/extension_manifest.rs index c4f7ecd07e7..f99b1cad910 100644 --- a/crates/extension/src/extension_manifest.rs +++ b/crates/extension/src/extension_manifest.rs @@ -409,14 +409,14 @@ fn manifest_from_old_manifest( lib: Default::default(), themes: { let mut themes = manifest_json.themes.into_values().collect::>(); - themes.sort(); + themes.sort_unstable(); themes.dedup(); themes }, icon_themes: Vec::new(), languages: { let mut languages = manifest_json.languages.into_values().collect::>(); - languages.sort(); + languages.sort_unstable(); languages.dedup(); languages }, diff --git a/crates/gpui/src/text_system.rs b/crates/gpui/src/text_system.rs index 043d37f679b..f3dc95bc579 100644 --- a/crates/gpui/src/text_system.rs +++ b/crates/gpui/src/text_system.rs @@ -93,7 +93,7 @@ impl TextSystem { .map(|font| font.family.to_string()), ); names.push(".SystemUIFont".to_string()); - names.sort(); + names.sort_unstable(); names.dedup(); names } diff --git a/crates/gpui_wgpu/src/cosmic_text_system.rs b/crates/gpui_wgpu/src/cosmic_text_system.rs index 456ba59c0a5..735a052a553 100644 --- a/crates/gpui_wgpu/src/cosmic_text_system.rs +++ b/crates/gpui_wgpu/src/cosmic_text_system.rs @@ -106,7 +106,7 @@ impl PlatformTextSystem for CosmicTextSystem { .faces() .filter_map(|face| face.families.first().map(|family| family.0.clone())) .collect_vec(); - result.sort(); + result.sort_unstable(); result.dedup(); result } diff --git a/crates/language/src/buffer.rs b/crates/language/src/buffer.rs index 81ffa31da7c..3f02305a4ac 100644 --- a/crates/language/src/buffer.rs +++ b/crates/language/src/buffer.rs @@ -4778,7 +4778,7 @@ impl BufferSnapshot { }) .filter(|(start, _, _)| chunk_range.contains(start)) .collect(); - unique_closes.sort(); + unique_closes.sort_unstable(); unique_closes.dedup(); // Build valid pairs by walking through closes in order diff --git a/crates/project/src/bookmark_store.rs b/crates/project/src/bookmark_store.rs index 841fb04af24..c66fdbf2836 100644 --- a/crates/project/src/bookmark_store.rs +++ b/crates/project/src/bookmark_store.rs @@ -321,7 +321,7 @@ impl BookmarkStore { } }; - rows.sort(); + rows.sort_unstable(); rows.dedup(); if rows.is_empty() { diff --git a/crates/project/src/lsp_store.rs b/crates/project/src/lsp_store.rs index e2b21ccdf51..bb9bdd7e843 100644 --- a/crates/project/src/lsp_store.rs +++ b/crates/project/src/lsp_store.rs @@ -12271,7 +12271,7 @@ impl LspStore { .iter() .filter_map(|(seed, v)| seed.worktree_id.eq(&worktree_id).then(|| v.id)) .collect::>(); - language_server_ids.sort(); + language_server_ids.sort_unstable(); language_server_ids.dedup(); // let abs_path = worktree_handle.read(cx).abs_path(); diff --git a/crates/recent_projects/src/recent_projects.rs b/crates/recent_projects/src/recent_projects.rs index 22b07679f96..2c69b75b865 100644 --- a/crates/recent_projects/src/recent_projects.rs +++ b/crates/recent_projects/src/recent_projects.rs @@ -140,7 +140,7 @@ pub async fn get_recent_projects( .iter() .flat_map(|workspace| workspace.identity_paths.paths().iter().cloned()) .collect(); - all_paths.sort(); + all_paths.sort_unstable(); all_paths.dedup(); let path_details = util::disambiguate::compute_disambiguation_details(&all_paths, |path, detail| { @@ -219,7 +219,7 @@ fn get_open_folders(workspace: &Workspace, cx: &App) -> Vec { .iter() .map(|wt| wt.read(cx).abs_path().to_path_buf()) .collect(); - all_paths.sort(); + all_paths.sort_unstable(); all_paths.dedup(); let path_details = util::disambiguate::compute_disambiguation_details(&all_paths, |path, detail| { diff --git a/crates/sidebar/src/sidebar.rs b/crates/sidebar/src/sidebar.rs index 6c2f6ea5489..5add7fe1d08 100644 --- a/crates/sidebar/src/sidebar.rs +++ b/crates/sidebar/src/sidebar.rs @@ -1406,7 +1406,7 @@ impl Sidebar { .iter() .flat_map(|group| group.key.path_list().paths().iter().cloned()) .collect(); - all_paths.sort(); + all_paths.sort_unstable(); all_paths.dedup(); let path_details = util::disambiguate::compute_disambiguation_details(&all_paths, |path, detail| {