Skip to content

Commit

Permalink
Improve search performance more
Browse files Browse the repository at this point in the history
  • Loading branch information
jackpot51 committed Oct 10, 2024
1 parent fd93917 commit f2e207b
Showing 1 changed file with 43 additions and 20 deletions.
63 changes: 43 additions & 20 deletions src/tab.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ use std::{
io::{BufRead, BufReader},
os::unix::fs::MetadataExt,
path::{Path, PathBuf},
sync::{atomic, Arc, Mutex},
sync::{atomic, Arc, Mutex, RwLock},
time::{Duration, Instant, SystemTime},
};
use tokio::sync::mpsc;
Expand Down Expand Up @@ -285,7 +285,7 @@ fn format_permissions(metadata: &Metadata, owner: PermissionOwner) -> String {
perms.join(" ")
}

struct FormatTime(std::time::SystemTime);
struct FormatTime(SystemTime);

impl FormatTime {
fn from_secs(secs: i64) -> Option<Self> {
Expand Down Expand Up @@ -321,7 +321,7 @@ impl Display for FormatTime {
}
}

fn format_time(time: std::time::SystemTime) -> FormatTime {
fn format_time(time: SystemTime) -> FormatTime {
FormatTime(time)
}

Expand Down Expand Up @@ -530,7 +530,7 @@ pub fn scan_path(tab_path: &PathBuf, sizes: IconSizes) -> Vec<Item> {
items
}

pub fn scan_search<F: Fn(PathBuf, String, Metadata) -> bool + Sync>(
pub fn scan_search<F: Fn(&Path, &str, Metadata) -> bool + Sync>(
tab_path: &PathBuf,
term: &str,
callback: F,
Expand Down Expand Up @@ -571,15 +571,16 @@ pub fn scan_search<F: Fn(PathBuf, String, Metadata) -> bool + Sync>(
if regex.is_match(file_name) {
let path = entry.path();

let metadata = match fs::metadata(&path) {
let metadata = match entry.metadata() {
Ok(ok) => ok,
Err(err) => {
log::warn!("failed to read metadata for entry at {:?}: {}", path, err);
return ignore::WalkState::Continue;
}
};

if !callback(path.to_path_buf(), file_name.to_string(), metadata) {
//TODO: use entry.into_path?
if !callback(path, file_name, metadata) {
return ignore::WalkState::Quit;
}
}
Expand Down Expand Up @@ -1036,6 +1037,13 @@ impl ItemMetadata {
Self::SimpleFile { .. } => false,
}
}

pub fn modified(&self) -> Option<SystemTime> {
match self {
Self::Path { metadata, .. } => metadata.modified().ok(),
_ => None,
}
}
}

#[derive(Clone, Debug)]
Expand Down Expand Up @@ -1430,6 +1438,7 @@ impl Mode {
struct SearchContext {
results_rx: mpsc::Receiver<(PathBuf, String, Metadata)>,
ready: Arc<atomic::AtomicBool>,
last_modified_opt: Arc<RwLock<Option<SystemTime>>>,
}

pub struct SearchContextWrapper(Option<SearchContext>);
Expand Down Expand Up @@ -1945,6 +1954,7 @@ impl Tab {
let min = range.0.min(range.1);
let max = range.0.max(range.1);
let (sort_name, sort_direction, _) = self.sort_options();
//TODO: this assumes the default sort order!
if sort_name == HeadingOptions::Name && sort_direction {
// A default/unsorted tab's view is consistent with how the
// Items are laid out internally (items_opt), so Items can be
Expand Down Expand Up @@ -2490,13 +2500,9 @@ impl Tab {
context.results_rx.blocking_recv()
{
//TODO: combine this with column_sort logic, they must match!
let get_modified = |x: &Item| match &x.metadata {
ItemMetadata::Path { metadata, .. } => metadata.modified().ok(),
_ => None,
};
let item_modified = metadata.modified().ok();
let index = match items.binary_search_by(|other| {
item_modified.cmp(&get_modified(&other))
item_modified.cmp(&other.metadata.modified())
}) {
Ok(index) => index,
Err(index) => index,
Expand All @@ -2516,6 +2522,11 @@ impl Tab {
}
if items.len() >= MAX_SEARCH_RESULTS {
items.truncate(MAX_SEARCH_RESULTS);
if let Some(last_modified) =
items.last().and_then(|item| item.metadata.modified())
{
*context.last_modified_opt.write().unwrap() = Some(last_modified);
}
}
} else {
log::warn!("search ready but items array is empty");
Expand Down Expand Up @@ -2763,13 +2774,8 @@ impl Tab {
}),
HeadingOptions::Modified => {
items.sort_by(|a, b| {
let get_modified = |x: &Item| match &x.metadata {
ItemMetadata::Path { metadata, .. } => metadata.modified().ok(),
_ => None,
};

let a_modified = get_modified(a.1);
let b_modified = get_modified(b.1);
let a_modified = a.1.metadata.modified();
let b_modified = b.1.metadata.modified();
if folders_first {
match (a.1.metadata.is_dir(), b.1.metadata.is_dir()) {
(true, false) => Ordering::Less,
Expand Down Expand Up @@ -4160,7 +4166,7 @@ impl Tab {
let message = {
let path = path.clone();
tokio::task::spawn_blocking(move || {
let start = std::time::Instant::now();
let start = Instant::now();
//TODO: configurable thumbnail size?
let thumbnail_size = (ICON_SIZE_GRID * ICON_SCALE_MAX) as u32;
let thumbnail = ItemThumbnail::new(&path, mime, thumbnail_size);
Expand Down Expand Up @@ -4201,12 +4207,14 @@ impl Tab {
let (results_tx, results_rx) = mpsc::channel(65536);

let ready = Arc::new(atomic::AtomicBool::new(false));
let last_modified_opt = Arc::new(RwLock::new(None));
output
.send(Message::SearchContext(
location.clone(),
SearchContextWrapper(Some(SearchContext {
results_rx,
ready: ready.clone(),
last_modified_opt: last_modified_opt.clone(),
})),
))
.await
Expand All @@ -4217,7 +4225,22 @@ impl Tab {
let output = output.clone();
tokio::task::spawn_blocking(move || {
scan_search(&path, &term, move |path, name, metadata| -> bool {
match results_tx.blocking_send((path, name, metadata)) {
// Don't send if the result is too old
if let Some(last_modified) = *last_modified_opt.read().unwrap() {
if let Ok(modified) = metadata.modified() {
if metadata.modified().ok() < Some(last_modified) {
return true;
}
} else {
return true;
}
}

match results_tx.blocking_send((
path.to_path_buf(),
name.to_string(),
metadata,
)) {
Ok(()) => {
if !ready.swap(true, atomic::Ordering::SeqCst) {
// Wake up update method
Expand Down

0 comments on commit f2e207b

Please sign in to comment.