From e1ca781dd75ffd3285a655ea1f559169bbcc3e83 Mon Sep 17 00:00:00 2001 From: Liu-Cheng Xu Date: Sun, 21 Apr 2024 12:26:30 +0800 Subject: [PATCH] . --- crates/maple_core/src/searcher/grep/mod.rs | 14 +-- .../src/searcher/grep/stoppable_searcher.rs | 94 ++++++++++--------- crates/maple_core/src/searcher/mod.rs | 14 +++ crates/types/src/matcher.rs | 20 ---- 4 files changed, 69 insertions(+), 73 deletions(-) diff --git a/crates/maple_core/src/searcher/grep/mod.rs b/crates/maple_core/src/searcher/grep/mod.rs index 1e8096cff..88f25c474 100644 --- a/crates/maple_core/src/searcher/grep/mod.rs +++ b/crates/maple_core/src/searcher/grep/mod.rs @@ -4,7 +4,7 @@ pub use self::stoppable_searcher::search; use self::stoppable_searcher::{FileResult, StoppableSearchImpl, UPDATE_INTERVAL}; use matcher::Matcher; use std::path::PathBuf; -use std::sync::atomic::{AtomicBool, AtomicUsize}; +use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; use std::time::Instant; use tokio::sync::mpsc::unbounded_channel; @@ -23,9 +23,7 @@ pub async fn cli_search(paths: Vec, matcher: Matcher) -> SearchResult { let stop_signal = Arc::new(AtomicBool::new(false)); - let search_info = SearchInfo { - total_processed: Arc::new(AtomicUsize::new(0)), - }; + let search_info = SearchInfo::new(); { let search_info = search_info.clone(); @@ -45,9 +43,7 @@ pub async fn cli_search(paths: Vec, matcher: Matcher) -> SearchResult { while let Some(file_result) = receiver.recv().await { matches.push(file_result); total_matched += 1; - let total_processed = search_info - .total_processed - .load(std::sync::atomic::Ordering::Relaxed); + let total_processed = search_info.total_processed.load(Ordering::Relaxed); if total_matched % 16 == 0 || total_processed % 16 == 0 { let now = Instant::now(); @@ -58,9 +54,7 @@ pub async fn cli_search(paths: Vec, matcher: Matcher) -> SearchResult { } } - let total_processed = search_info - .total_processed - .load(std::sync::atomic::Ordering::SeqCst) as u64; + let total_processed = search_info.total_processed.load(Ordering::SeqCst) as u64; SearchResult { matches, diff --git a/crates/maple_core/src/searcher/grep/stoppable_searcher.rs b/crates/maple_core/src/searcher/grep/stoppable_searcher.rs index 5b6bd51be..73d46b88b 100644 --- a/crates/maple_core/src/searcher/grep/stoppable_searcher.rs +++ b/crates/maple_core/src/searcher/grep/stoppable_searcher.rs @@ -6,7 +6,7 @@ use icon::Icon; use ignore::{DirEntry, WalkState}; use matcher::Matcher; use std::path::PathBuf; -use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; +use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; use std::time::{Duration, Instant}; use tokio::sync::mpsc::{unbounded_channel, UnboundedSender}; @@ -137,8 +137,13 @@ impl StoppableSearchImpl { }); if let Some(file_result) = maybe_file_result { - // Discontinue if the sender has been dropped. - return Ok(sender.send(file_result).is_ok()); + search_info.total_matched.fetch_add(1, Ordering::Relaxed); + + // Only send the item when its rank is higher than the lowest rank. + if file_result.rank > *search_info.lowest_rank.read() { + // Discontinue if the sender has been dropped. + return Ok(sender.send(file_result).is_ok()); + } } Ok(true) @@ -182,6 +187,12 @@ impl BestFileResults { fn sort(&mut self) { self.results.sort_unstable_by(|a, b| b.rank.cmp(&a.rank)); } + + #[inline] + fn replace_last(&mut self, new: FileResult) { + let index = self.results.len() - 1; + self.results[index] = new; + } } pub async fn search(query: String, matcher: Matcher, search_context: SearchContext) { @@ -202,9 +213,7 @@ pub async fn search(query: String, matcher: Matcher, search_context: SearchConte let (sender, mut receiver) = unbounded_channel(); - let search_info = SearchInfo { - total_processed: Arc::new(AtomicUsize::new(0)), - }; + let search_info = SearchInfo::new(); std::thread::Builder::new() .name("grep-worker".into()) @@ -287,50 +296,48 @@ pub async fn search(query: String, matcher: Matcher, search_context: SearchConte best_results.past = now; } } else { - let last = best_results - .results - .last_mut() - .expect("Max capacity is non-zero; qed"); - - let new = file_result; - if new.rank > last.rank { - *last = new; - best_results.sort(); - } + best_results.replace_last(file_result); + best_results.sort(); + let total_matched = search_info.total_matched.load(Ordering::Relaxed); let total_processed = search_info.total_processed.load(Ordering::Relaxed); - if total_matched % 16 == 0 || total_processed % 16 == 0 { - let now = Instant::now(); - if now > best_results.past + UPDATE_INTERVAL { - let display_lines = to_display_lines(&best_results.results, icon); - - let visible_highlights = display_lines - .indices - .iter() - .map(|line_highlights| { - line_highlights - .iter() - .copied() - .filter(|&x| x <= line_width) - .collect::>() - }) - .collect::>(); - - if best_results.last_lines != display_lines.lines.as_slice() - || best_results.last_visible_highlights != visible_highlights - { - progressor.update_all(&display_lines, total_matched, total_processed); - best_results.last_lines = display_lines.lines; - best_results.last_visible_highlights = visible_highlights; - } else { - progressor.quick_update(total_matched, total_processed) - } + let now = Instant::now(); + if now > best_results.past + UPDATE_INTERVAL { + let display_lines = to_display_lines(&best_results.results, icon); - best_results.past = now; + let visible_highlights = display_lines + .indices + .iter() + .map(|line_highlights| { + line_highlights + .iter() + .copied() + .filter(|&x| x <= line_width) + .collect::>() + }) + .collect::>(); + + if best_results.last_lines != display_lines.lines.as_slice() + || best_results.last_visible_highlights != visible_highlights + { + progressor.update_all(&display_lines, total_matched, total_processed); + best_results.last_lines = display_lines.lines; + best_results.last_visible_highlights = visible_highlights; + } else { + progressor.quick_update(total_matched, total_processed) } + + best_results.past = now; } } + + // best_results list is sorted now. + *search_info.lowest_rank.write() = best_results + .results + .last() + .expect("results must not be empty; qed") + .rank; } if stop_signal.load(Ordering::SeqCst) { @@ -341,6 +348,7 @@ pub async fn search(query: String, matcher: Matcher, search_context: SearchConte let display_lines = to_display_lines(&best_results.results, icon); + let total_matched = search_info.total_matched.load(Ordering::SeqCst); let total_processed = search_info.total_processed.load(Ordering::SeqCst); progressor.on_finished(display_lines, total_matched, total_processed); diff --git a/crates/maple_core/src/searcher/mod.rs b/crates/maple_core/src/searcher/mod.rs index 3b62ad86b..b1af53a1c 100644 --- a/crates/maple_core/src/searcher/mod.rs +++ b/crates/maple_core/src/searcher/mod.rs @@ -6,18 +6,32 @@ pub mod tagfiles; use crate::stdio_server::Vim; use icon::Icon; use ignore::{WalkBuilder, WalkParallel}; +use parking_lot::RwLock; use paths::AbsPathBuf; use serde::{Deserialize, Serialize}; use std::path::PathBuf; use std::sync::atomic::{AtomicBool, AtomicUsize}; use std::sync::Arc; +use types::Rank; // Shareable searching info. #[derive(Clone, Debug)] pub struct SearchInfo { + pub lowest_rank: Arc>, + pub total_matched: Arc, pub total_processed: Arc, } +impl SearchInfo { + pub fn new() -> Self { + Self { + lowest_rank: Arc::new(RwLock::new(Rank::default())), + total_matched: Arc::new(AtomicUsize::new(0)), + total_processed: Arc::new(AtomicUsize::new(0)), + } + } +} + #[derive(Debug, Clone)] pub struct SearchContext { pub icon: Icon, diff --git a/crates/types/src/matcher.rs b/crates/types/src/matcher.rs index 985968f3a..dd4a5bbe5 100644 --- a/crates/types/src/matcher.rs +++ b/crates/types/src/matcher.rs @@ -41,26 +41,6 @@ impl From<[Score; 4]> for Rank { } } -impl Rank { - /// Packs four i32 values into a single u64. - pub fn as_u64(&self) -> u64 { - let a = self.0[0] as u64 & 0xFFFF_FFFF; - let b = self.0[1] as u64 & 0xFFFF_FFFF; - let c = self.0[2] as u64 & 0xFFFF_FFFF; - let d = self.0[3] as u64 & 0xFFFF_FFFF; - (a << 48) | (b << 32) | (c << 16) | d - } - - /// Unpacks a u64 into four i32 values. - pub fn from_u64(value: u64) -> Self { - let a = (value >> 48) as i32; - let b = ((value >> 32) & 0xFFFF_FFFF) as i32; - let c = ((value >> 16) & 0xFFFF_FFFF) as i32; - let d = (value & 0xFFFF_FFFF) as i32; - Self([a, b, c, d]) - } -} - #[derive(Debug, Clone)] pub struct RankCalculator { criteria: Vec,