Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 44 additions & 5 deletions crates/project_panel/benches/sorting.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
use criterion::{Criterion, criterion_group, criterion_main};
use project::{Entry, EntryKind, GitEntry, ProjectEntryId};
use project_panel::par_sort_worktree_entries;
use project_panel::{par_sort_worktree_entries, par_sort_worktree_entries_with_mode};
use settings::ProjectPanelSortMode;
use std::sync::Arc;
use util::rel_path::RelPath;

fn load_linux_repo_snapshot() -> Vec<GitEntry> {
let file = std::fs::read_to_string(
"/Users/hiro/Projects/zed/crates/project_panel/benches/linux_repo_snapshot.txt",
)
let file = std::fs::read_to_string(concat!(
env!("CARGO_MANIFEST_DIR"),
"/benches/linux_repo_snapshot.txt"
))
.expect("Failed to read file");
file.lines()
.filter_map(|line| {
Expand Down Expand Up @@ -42,13 +44,50 @@ fn load_linux_repo_snapshot() -> Vec<GitEntry> {
}
fn criterion_benchmark(c: &mut Criterion) {
let snapshot = load_linux_repo_snapshot();
c.bench_function("Sort linux worktree snapshot", |b| {

c.bench_function("Sort linux worktree snapshot (legacy)", |b| {
b.iter_batched(
|| snapshot.clone(),
|mut snapshot| par_sort_worktree_entries(&mut snapshot),
criterion::BatchSize::LargeInput,
);
});

c.bench_function("Sort linux worktree snapshot (DirectoriesFirst)", |b| {
b.iter_batched(
|| snapshot.clone(),
|mut snapshot| {
par_sort_worktree_entries_with_mode(
&mut snapshot,
ProjectPanelSortMode::DirectoriesFirst,
)
},
criterion::BatchSize::LargeInput,
);
});

c.bench_function("Sort linux worktree snapshot (Mixed)", |b| {
b.iter_batched(
|| snapshot.clone(),
|mut snapshot| {
par_sort_worktree_entries_with_mode(
&mut snapshot,
ProjectPanelSortMode::Mixed,
)
},
criterion::BatchSize::LargeInput,
);
});

c.bench_function("Sort linux worktree snapshot (MacosLike)", |b| {
b.iter_batched(
|| snapshot.clone(),
|mut snapshot| {
par_sort_worktree_entries_with_mode(&mut snapshot, ProjectPanelSortMode::MacosLike)
},
criterion::BatchSize::LargeInput,
);
});
}

criterion_group!(benches, criterion_benchmark);
Expand Down
57 changes: 45 additions & 12 deletions crates/project_panel/src/project_panel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -679,6 +679,9 @@ impl ProjectPanel {
if project_panel_settings.hide_hidden != new_settings.hide_hidden {
this.update_visible_entries(None, false, false, window, cx);
}
if project_panel_settings.sort_mode != new_settings.sort_mode {
this.update_visible_entries(None, false, false, window, cx);
}
if project_panel_settings.sticky_scroll && !new_settings.sticky_scroll {
this.sticky_items_count = 0;
}
Expand Down Expand Up @@ -2077,7 +2080,8 @@ impl ProjectPanel {
.map(|entry| entry.to_owned())
.collect();

sort_worktree_entries(&mut siblings);
let mode = ProjectPanelSettings::get_global(cx).sort_mode;
sort_worktree_entries_with_mode(&mut siblings, mode);
let sibling_entry_index = siblings
.iter()
.position(|sibling| sibling.id == latest_entry.id)?;
Expand Down Expand Up @@ -3203,6 +3207,7 @@ impl ProjectPanel {
let settings = ProjectPanelSettings::get_global(cx);
let auto_collapse_dirs = settings.auto_fold_dirs;
let hide_gitignore = settings.hide_gitignore;
let sort_mode = settings.sort_mode;
let project = self.project.read(cx);
let repo_snapshots = project.git_store().read(cx).repo_snapshots(cx);

Expand Down Expand Up @@ -3413,7 +3418,10 @@ impl ProjectPanel {
entry_iter.advance();
}

par_sort_worktree_entries(&mut visible_worktree_entries);
par_sort_worktree_entries_with_mode(
&mut visible_worktree_entries,
sort_mode,
);
new_state.visible_entries.push(VisibleEntriesForWorktree {
worktree_id,
entries: visible_worktree_entries,
Expand Down Expand Up @@ -6059,21 +6067,46 @@ impl ClipboardEntry {
}
}

fn cmp<T: AsRef<Entry>>(lhs: T, rhs: T) -> cmp::Ordering {
let entry_a = lhs.as_ref();
let entry_b = rhs.as_ref();
util::paths::compare_rel_paths(
(&entry_a.path, entry_a.is_file()),
(&entry_b.path, entry_b.is_file()),
)
#[inline]
fn cmp_directories_first(a: &Entry, b: &Entry) -> cmp::Ordering {
util::paths::compare_rel_paths((&a.path, a.is_file()), (&b.path, b.is_file()))
}

#[inline]
fn cmp_mixed(a: &Entry, b: &Entry) -> cmp::Ordering {
util::paths::compare_rel_paths_mixed((&a.path, a.is_file()), (&b.path, b.is_file()))
}

#[inline]
fn cmp_macos_like(a: &Entry, b: &Entry) -> cmp::Ordering {
util::paths::compare_rel_paths_macos_like((&a.path, a.is_file()), (&b.path, b.is_file()))
}

#[inline]
fn cmp_with_mode(a: &Entry, b: &Entry, mode: &settings::ProjectPanelSortMode) -> cmp::Ordering {
match mode {
settings::ProjectPanelSortMode::DirectoriesFirst => cmp_directories_first(a, b),
settings::ProjectPanelSortMode::Mixed => cmp_mixed(a, b),
settings::ProjectPanelSortMode::MacosLike => cmp_macos_like(a, b),
}
}

pub fn sort_worktree_entries_with_mode(
entries: &mut [impl AsRef<Entry>],
mode: settings::ProjectPanelSortMode,
) {
entries.sort_by(|lhs, rhs| cmp_with_mode(lhs.as_ref(), rhs.as_ref(), &mode));
}

pub fn sort_worktree_entries(entries: &mut [impl AsRef<Entry>]) {
entries.sort_by(|lhs, rhs| cmp(lhs, rhs));
pub fn par_sort_worktree_entries_with_mode(
entries: &mut Vec<GitEntry>,
mode: settings::ProjectPanelSortMode,
) {
entries.par_sort_by(|lhs, rhs| cmp_with_mode(lhs, rhs, &mode));
}

pub fn par_sort_worktree_entries(entries: &mut Vec<GitEntry>) {
entries.par_sort_by(|lhs, rhs| cmp(lhs, rhs));
par_sort_worktree_entries_with_mode(entries, settings::ProjectPanelSortMode::DirectoriesFirst);
}

#[cfg(test)]
Expand Down
9 changes: 8 additions & 1 deletion crates/project_panel/src/project_panel_settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ use editor::EditorSettings;
use gpui::Pixels;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use settings::{DockSide, ProjectPanelEntrySpacing, Settings, ShowDiagnostics, ShowIndentGuides};
use settings::{
DockSide, ProjectPanelEntrySpacing, ProjectPanelSortMode, Settings, ShowDiagnostics,
ShowIndentGuides,
};
use ui::{
px,
scrollbars::{ScrollbarVisibility, ShowScrollbar},
Expand Down Expand Up @@ -30,6 +33,7 @@ pub struct ProjectPanelSettings {
pub hide_hidden: bool,
pub drag_and_drop: bool,
pub open_file_on_paste: bool,
pub sort_mode: ProjectPanelSortMode,
}

#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
Expand Down Expand Up @@ -81,6 +85,9 @@ impl Settings for ProjectPanelSettings {
hide_hidden: project_panel.hide_hidden.unwrap(),
drag_and_drop: project_panel.drag_and_drop.unwrap(),
open_file_on_paste: project_panel.open_file_on_paste.unwrap(),
sort_mode: project_panel
.sort_mode
.unwrap_or(ProjectPanelSortMode::DirectoriesFirst),
}
}
}
Loading