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
This commit is contained in:
Miguel Raz Guzmán Macedo 2026-06-08 13:47:30 -06:00 committed by GitHub
parent cc105a4459
commit 78658778a2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 13 additions and 13 deletions

View file

@ -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:

View file

@ -409,14 +409,14 @@ fn manifest_from_old_manifest(
lib: Default::default(),
themes: {
let mut themes = manifest_json.themes.into_values().collect::<Vec<_>>();
themes.sort();
themes.sort_unstable();
themes.dedup();
themes
},
icon_themes: Vec::new(),
languages: {
let mut languages = manifest_json.languages.into_values().collect::<Vec<_>>();
languages.sort();
languages.sort_unstable();
languages.dedup();
languages
},

View file

@ -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
}

View file

@ -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
}

View file

@ -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

View file

@ -321,7 +321,7 @@ impl BookmarkStore {
}
};
rows.sort();
rows.sort_unstable();
rows.dedup();
if rows.is_empty() {

View file

@ -12271,7 +12271,7 @@ impl LspStore {
.iter()
.filter_map(|(seed, v)| seed.worktree_id.eq(&worktree_id).then(|| v.id))
.collect::<Vec<_>>();
language_server_ids.sort();
language_server_ids.sort_unstable();
language_server_ids.dedup();
// let abs_path = worktree_handle.read(cx).abs_path();

View file

@ -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<OpenFolderEntry> {
.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| {

View file

@ -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| {