From 5da33f6d024f537cca4d390705c24ed8418890e4 Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Thu, 25 Sep 2025 15:16:53 +0200 Subject: [PATCH] Sort project panel entries in parallel Co-authored-by: Smit Barmase --- Cargo.lock | 1 + crates/project/src/project.rs | 11 ------ crates/project_panel/Cargo.toml | 1 + crates/project_panel/src/project_panel.rs | 41 +++++++++++++++++------ 4 files changed, 33 insertions(+), 21 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f131e9ad52ff746650a633a8584042c8018370de..1580a51b78a04d8f87d594b2e4f17ded6783db0c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12149,6 +12149,7 @@ dependencies = [ "menu", "pretty_assertions", "project", + "rayon", "schemars 1.0.1", "search", "serde", diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index 1b85bda8513e5d82a73041f4fcafad58ab59e4fe..dd4e090641fbc0bdb088a1dfd189d1c7e4b60ab1 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -5539,17 +5539,6 @@ impl Completion { } } -pub fn sort_worktree_entries(entries: &mut [impl AsRef]) { - entries.sort_by(|entry_a, entry_b| { - let entry_a = entry_a.as_ref(); - let entry_b = entry_b.as_ref(); - compare_paths( - (entry_a.path.as_std_path(), entry_a.is_file()), - (entry_b.path.as_std_path(), entry_b.is_file()), - ) - }); -} - fn proto_to_prompt(level: proto::language_server_prompt_request::Level) -> gpui::PromptLevel { match level { proto::language_server_prompt_request::Level::Info(_) => gpui::PromptLevel::Info, diff --git a/crates/project_panel/Cargo.toml b/crates/project_panel/Cargo.toml index 5088b81a01a929fab6919644052c76193b48ffba..ffce089e45a60537a52ca66fe76fa1974a39490c 100644 --- a/crates/project_panel/Cargo.toml +++ b/crates/project_panel/Cargo.toml @@ -32,6 +32,7 @@ serde_json.workspace = true settings.workspace = true smallvec.workspace = true theme.workspace = true +rayon.workspace = true ui.workspace = true util.workspace = true client.workspace = true diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index a593b125f79c15cf3a7985abf8543f09e4262de6..ee56677aefe3dcd0176159e02a3c6a7d8ed146ce 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -17,13 +17,14 @@ use file_icons::FileIcons; use git::status::GitSummary; use git_ui::file_diff_view::FileDiffView; use gpui::{ - Action, AnyElement, App, AsyncWindowContext, Bounds, ClipboardItem, Context, CursorStyle, - DismissEvent, Div, DragMoveEvent, Entity, EventEmitter, ExternalPaths, FocusHandle, Focusable, - Hsla, InteractiveElement, KeyContext, ListHorizontalSizingBehavior, ListSizingBehavior, - Modifiers, ModifiersChangedEvent, MouseButton, MouseDownEvent, ParentElement, Pixels, Point, - PromptLevel, Render, ScrollStrategy, Stateful, Styled, Subscription, Task, - UniformListScrollHandle, WeakEntity, Window, actions, anchored, deferred, div, hsla, - linear_color_stop, linear_gradient, point, px, size, transparent_white, uniform_list, + Action, AnyElement, App, AsyncWindowContext, BackgroundExecutor, Bounds, ClipboardItem, + Context, CursorStyle, DismissEvent, Div, DragMoveEvent, Entity, EventEmitter, ExternalPaths, + FocusHandle, Focusable, Hsla, InteractiveElement, KeyContext, ListHorizontalSizingBehavior, + ListSizingBehavior, Modifiers, ModifiersChangedEvent, MouseButton, MouseDownEvent, + ParentElement, Pixels, Point, PromptLevel, Render, ScrollStrategy, Stateful, Styled, + Subscription, Task, UniformListScrollHandle, WeakEntity, Window, actions, anchored, deferred, + div, hsla, linear_color_stop, linear_gradient, point, px, size, transparent_white, + uniform_list, }; use language::DiagnosticSeverity; use menu::{Confirm, SelectFirst, SelectLast, SelectNext, SelectPrevious}; @@ -34,6 +35,7 @@ use project::{ project_settings::GoToDiagnosticSeverityFilter, }; use project_panel_settings::ProjectPanelSettings; +use rayon::slice::ParallelSliceMut; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use settings::{ @@ -2025,7 +2027,7 @@ impl ProjectPanel { .map(|entry| entry.to_owned()) .collect(); - project::sort_worktree_entries(&mut siblings); + sort_worktree_entries(&mut siblings); let sibling_entry_index = siblings .iter() .position(|sibling| sibling.id == latest_entry.id)?; @@ -3080,6 +3082,7 @@ impl ProjectPanel { .collect(); let hide_root = settings.hide_root && visible_worktrees.len() == 1; self.update_visible_entries_task = cx.spawn(async move |this, cx| { + let executor = cx.background_executor().clone(); let new_state = cx .background_spawn(async move { for worktree_snapshot in visible_worktrees { @@ -3266,8 +3269,8 @@ impl ProjectPanel { entry_iter.advance(); } - project::sort_worktree_entries(&mut visible_worktree_entries); - + let visible_worktree_entries = + par_sort_worktree_entries(visible_worktree_entries); new_state.visible_entries.push(VisibleEntriesForWorktree { worktree_id, entries: visible_worktree_entries, @@ -5885,5 +5888,23 @@ impl ClipboardEntry { } } +fn cmp>(lhs: T, rhs: T) -> cmp::Ordering { + let entry_a = lhs.as_ref(); + let entry_b = rhs.as_ref(); + compare_paths( + (entry_a.path.as_std_path(), entry_a.is_file()), + (entry_b.path.as_std_path(), entry_b.is_file()), + ) +} + +fn sort_worktree_entries(entries: &mut [impl AsRef]) { + entries.sort_by(|lhs, rhs| cmp(lhs, rhs)); +} + +fn par_sort_worktree_entries + Send + Clone>(mut entries: Vec) -> Vec { + entries.par_sort_by(|lhs, rhs| cmp(lhs, rhs)); + entries +} + #[cfg(test)] mod project_panel_tests;