From 4cef25eff8b247d0cbbc4f6cc7ef8ba2ba96ad21 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 13 Apr 2021 19:15:08 -0600 Subject: [PATCH] Replace easy-parallel with scoped-pool for path searches The easy-parallel crate spawned new threads on each call, which was resulting in way too many threads. Co-Authored-By: Brooks Swinnerton <934497+bswinnerton@users.noreply.github.com> --- Cargo.lock | 32 +++++++++++++++++++++++++++++++- gpui/Cargo.toml | 3 ++- gpui/src/app.rs | 6 ++++++ gpui/src/lib.rs | 1 + zed/src/file_finder.rs | 3 ++- zed/src/worktree/fuzzy.rs | 16 ++++++++-------- zed/src/worktree/worktree.rs | 6 ++++-- 7 files changed, 54 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5692f38a16..119ba96e46 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -498,6 +498,12 @@ dependencies = [ "cfg-if 1.0.0", ] +[[package]] +name = "crossbeam" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd66663db5a988098a89599d4857919b3acf7f61402e61365acfd3919857b9be" + [[package]] name = "crossbeam-channel" version = "0.4.4" @@ -925,6 +931,7 @@ dependencies = [ "rand 0.8.3", "replace_with", "resvg", + "scoped-pool", "seahash", "serde", "serde_json", @@ -1067,7 +1074,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd96ffd135b2fd7b973ac026d28085defbe8983df057ced3eb4f2130b0831312" dependencies = [ - "scopeguard", + "scopeguard 1.1.0", ] [[package]] @@ -1676,12 +1683,29 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "scoped-pool" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "817a3a15e704545ce59ed2b5c60a5d32bda4d7869befb8b36667b658a6c00b43" +dependencies = [ + "crossbeam", + "scopeguard 0.1.2", + "variance", +] + [[package]] name = "scoped-tls" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" +[[package]] +name = "scopeguard" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59a076157c1e2dc561d8de585151ee6965d910dd4dcb5dabb7ae3e83981a6c57" + [[package]] name = "scopeguard" version = "1.1.0" @@ -2074,6 +2098,12 @@ dependencies = [ "ctor", ] +[[package]] +name = "variance" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3abfc2be1fb59663871379ea884fd81de80c496f2274e021c01d6fe56cd77b05" + [[package]] name = "vec-arena" version = "1.0.0" diff --git a/gpui/Cargo.toml b/gpui/Cargo.toml index d87883bab6..0f11bd1de2 100644 --- a/gpui/Cargo.toml +++ b/gpui/Cargo.toml @@ -18,8 +18,9 @@ pathfinder_geometry = "0.5" rand = "0.8.3" replace_with = "0.1.7" resvg = "0.14" +scoped-pool = "1.0.0" seahash = "4.1" -serde = { version = "1.0.125", features = ["derive"] } +serde = {version = "1.0.125", features = ["derive"]} serde_json = "1.0.64" smallvec = "1.6.1" smol = "1.2" diff --git a/gpui/src/app.rs b/gpui/src/app.rs index 738ecd79ce..6453e4124e 100644 --- a/gpui/src/app.rs +++ b/gpui/src/app.rs @@ -414,6 +414,7 @@ impl MutableAppContext { windows: HashMap::new(), ref_counts: Arc::new(Mutex::new(RefCounts::default())), background: Arc::new(executor::Background::new()), + scoped_pool: scoped_pool::Pool::new(num_cpus::get()), }, actions: HashMap::new(), global_actions: HashMap::new(), @@ -1336,6 +1337,7 @@ pub struct AppContext { windows: HashMap, background: Arc, ref_counts: Arc>, + scoped_pool: scoped_pool::Pool, } impl AppContext { @@ -1374,6 +1376,10 @@ impl AppContext { pub fn background_executor(&self) -> &Arc { &self.background } + + pub fn scoped_pool(&self) -> &scoped_pool::Pool { + &self.scoped_pool + } } impl ReadModel for AppContext { diff --git a/gpui/src/lib.rs b/gpui/src/lib.rs index ee8c544a83..edf14bc65c 100644 --- a/gpui/src/lib.rs +++ b/gpui/src/lib.rs @@ -29,3 +29,4 @@ pub use presenter::{ AfterLayoutContext, Axis, DebugContext, EventContext, LayoutContext, PaintContext, SizeConstraint, Vector2FExt, }; +pub use scoped_pool; diff --git a/zed/src/file_finder.rs b/zed/src/file_finder.rs index b27189814c..654017556d 100644 --- a/zed/src/file_finder.rs +++ b/zed/src/file_finder.rs @@ -347,8 +347,9 @@ impl FileFinder { fn spawn_search(&mut self, query: String, ctx: &mut ViewContext) { let worktrees = self.worktrees(ctx.as_ref()); let search_id = util::post_inc(&mut self.search_count); + let pool = ctx.app().scoped_pool().clone(); let task = ctx.background_executor().spawn(async move { - let matches = match_paths(worktrees.as_slice(), &query, false, false, 100); + let matches = match_paths(worktrees.as_slice(), &query, false, false, 100, pool); (search_id, matches) }); diff --git a/zed/src/worktree/fuzzy.rs b/zed/src/worktree/fuzzy.rs index e6baeec962..c4a3d451ed 100644 --- a/zed/src/worktree/fuzzy.rs +++ b/zed/src/worktree/fuzzy.rs @@ -1,4 +1,4 @@ -use easy_parallel::Parallel; +use gpui::scoped_pool; use super::char_bag::CharBag; @@ -54,6 +54,7 @@ pub fn match_paths( include_ignored: bool, smart_case: bool, max_results: usize, + pool: scoped_pool::Pool, ) -> Vec { let lowercase_query = query.to_lowercase().chars().collect::>(); let query = query.chars().collect::>(); @@ -68,10 +69,9 @@ pub fn match_paths( let segment_size = (path_count + cpus - 1) / cpus; let mut segment_results = (0..cpus).map(|_| BinaryHeap::new()).collect::>(); - Parallel::new() - .each( - segment_results.iter_mut().enumerate(), - |(segment_idx, results)| { + pool.scoped(|scope| { + for (segment_idx, results) in segment_results.iter_mut().enumerate() { + scope.execute(move || { let segment_start = segment_idx * segment_size; let segment_end = segment_start + segment_size; @@ -115,9 +115,9 @@ pub fn match_paths( } tree_start = tree_end; } - }, - ) - .run(); + }) + } + }); let mut results = segment_results .into_iter() diff --git a/zed/src/worktree/worktree.rs b/zed/src/worktree/worktree.rs index 2e63ad117f..60fab4c5a9 100644 --- a/zed/src/worktree/worktree.rs +++ b/zed/src/worktree/worktree.rs @@ -11,7 +11,7 @@ use crate::{ use anyhow::{anyhow, Result}; use crossbeam_channel as channel; use easy_parallel::Parallel; -use gpui::{AppContext, Entity, ModelContext, ModelHandle, Task}; +use gpui::{scoped_pool, AppContext, Entity, ModelContext, ModelHandle, Task}; use ignore::dir::{Ignore, IgnoreBuilder}; use parking_lot::RwLock; use smol::prelude::*; @@ -606,6 +606,7 @@ pub fn match_paths( include_ignored: bool, smart_case: bool, max_results: usize, + pool: scoped_pool::Pool, ) -> Vec { let tree_states = trees.iter().map(|tree| tree.0.read()).collect::>(); fuzzy::match_paths( @@ -634,6 +635,7 @@ pub fn match_paths( include_ignored, smart_case, max_results, + pool, ) } @@ -674,7 +676,7 @@ mod test { app.read(|ctx| { let tree = tree.read(ctx); assert_eq!(tree.file_count(), 4); - let results = match_paths(&[tree.clone()], "bna", false, false, 10) + let results = match_paths(&[tree.clone()], "bna", false, false, 10, ctx.scoped_pool().clone()) .iter() .map(|result| tree.entry_path(result.entry_id)) .collect::, _>>()