Remove multithreading for sorting

The relevant processes are so fast, mutexes and mutex locks are so
expensive, and iterators so efficient, that it's actually faster to run
single-threaded across all the data than to spin up a bunch of threads
and have them basically spinlock waiting for the global mutex involved
either directly or in a channel.

ivy_files(kubernetes)   time:   [10.209 ms 10.245 ms 10.286 ms]
                        change: [-36.781% -36.178% -35.601%] (p = 0.00 < 0.05)
                        Performance has improved.

ivy_match(file.lua)     time:   [1.1626 µs 1.1668 µs 1.1709 µs]
                        change: [+0.2131% +1.5409% +2.9109%] (p = 0.02 < 0.05)
                        Change within noise threshold.
This commit is contained in:
Xymist 2022-08-26 16:29:11 +01:00
parent 7fb8be541a
commit cec8393770
4 changed files with 14 additions and 32 deletions

View file

@ -1,5 +1,7 @@
use ivyrs::inner_files; use ivyrs::inner_files;
pub fn main() { pub fn main() {
inner_files("file.go".to_owned(), "/tmp/ivy-trees/kubernetes".to_owned()); let res = inner_files("file.go".to_owned(), "/tmp/ivy-trees/kubernetes".to_owned());
println!("{}", res);
} }

View file

@ -52,7 +52,7 @@ pub extern "C" fn ivy_match(c_pattern: *const c_char, c_text: *const c_char) ->
pub fn inner_match(pattern: String, text: String) -> i32 { pub fn inner_match(pattern: String, text: String) -> i32 {
let m = matcher::Matcher::new(pattern); let m = matcher::Matcher::new(pattern);
m.score(text) as i32 m.score(text.as_str()) as i32
} }
#[no_mangle] #[no_mangle]

View file

@ -15,9 +15,9 @@ impl Matcher {
} }
} }
pub fn score(&self, text: String) -> i64 { pub fn score(&self, text: &str) -> i64 {
self.matcher self.matcher
.fuzzy_indices(&text, &self.pattern) .fuzzy_indices(text, &self.pattern)
.map(|(score, _indices)| score) .map(|(score, _indices)| score)
.unwrap_or_default() .unwrap_or_default()
} }

View file

@ -24,36 +24,16 @@ impl Options {
} }
pub fn sort_strings(options: Options, strings: Vec<String>) -> Vec<Match> { pub fn sort_strings(options: Options, strings: Vec<String>) -> Vec<Match> {
let mut matches = Vec::new(); let matcher = matcher::Matcher::new(options.pattern);
let matcher = Arc::new(matcher::Matcher::new(options.pattern));
let pool = thread_pool::ThreadPool::new(std::thread::available_parallelism().unwrap().get()); let mut matches = strings
.into_iter()
let (tx, rx) = mpsc::channel::<Match>(); .map(|candidate| Match {
score: matcher.score(candidate.as_str()),
for string in strings { content: candidate,
let thread_matcher = Arc::clone(&matcher);
let thread_transmitter = tx.clone();
pool.execute(move || {
let score = thread_matcher.score(string.to_string());
if score > 25 {
thread_transmitter
.send(Match {
score,
content: string,
})
.expect("Failed to push data to channel");
}
}) })
} .filter(|m| m.score > 25)
.collect::<Vec<Match>>();
drop(pool);
drop(tx);
while let Ok(result) = rx.recv() {
matches.push(result)
}
matches.sort_by(|a, b| a.score.cmp(&b.score)); matches.sort_by(|a, b| a.score.cmp(&b.score));
matches matches
} }