Compare commits

...

1 Commits

Author SHA1 Message Date
Thorsten Ball
f312763c33 wip: Performance improvements for project search
Do not merge. Need to check with Conrad.

Co-authored-by: Antonio <antonio@zed.dev>
2024-08-27 14:48:17 +02:00
4 changed files with 43 additions and 32 deletions

View File

@@ -6,7 +6,7 @@ use crate::{
use anyhow::{anyhow, Context as _, Result}; use anyhow::{anyhow, Context as _, Result};
use collections::{hash_map, HashMap, HashSet}; use collections::{hash_map, HashMap, HashSet};
use fs::Fs; use fs::Fs;
use futures::{channel::oneshot, stream::FuturesUnordered, StreamExt as _}; use futures::{channel::oneshot, stream::FuturesUnordered, StreamExt};
use git::blame::Blame; use git::blame::Blame;
use gpui::{ use gpui::{
AppContext, AsyncAppContext, Context as _, EventEmitter, Model, ModelContext, Task, WeakModel, AppContext, AsyncAppContext, Context as _, EventEmitter, Model, ModelContext, Task, WeakModel,
@@ -788,7 +788,9 @@ impl BufferStore {
fs: Arc<dyn Fs>, fs: Arc<dyn Fs>,
cx: &mut ModelContext<Self>, cx: &mut ModelContext<Self>,
) -> Receiver<Model<Buffer>> { ) -> Receiver<Model<Buffer>> {
let (tx, rx) = smol::channel::unbounded(); const MAGIC_NUMBER: usize = 64;
let (tx, rx) = smol::channel::bounded(MAGIC_NUMBER);
let open_buffers = self.find_open_search_candidates(query, cx); let open_buffers = self.find_open_search_candidates(query, cx);
let skip_entries: HashSet<_> = open_buffers let skip_entries: HashSet<_> = open_buffers
.iter() .iter()
@@ -796,33 +798,38 @@ impl BufferStore {
.collect(); .collect();
let limit = limit.saturating_sub(open_buffers.len()); let limit = limit.saturating_sub(open_buffers.len());
for open_buffer in open_buffers {
tx.send_blocking(open_buffer).ok();
}
let match_rx = self.worktree_store.update(cx, |worktree_store, cx| { let mut project_paths_rx = self
worktree_store.find_search_candidates(query.clone(), limit, skip_entries, fs, cx) .worktree_store
}); .update(cx, |worktree_store, cx| {
worktree_store.find_search_candidates(query.clone(), limit, skip_entries, fs, cx)
})
.chunks(MAGIC_NUMBER);
const MAX_CONCURRENT_BUFFER_OPENS: usize = 8; cx.spawn(|this, mut cx| async move {
for open_buffer in open_buffers {
tx.send(open_buffer).await.ok();
}
for _ in 0..MAX_CONCURRENT_BUFFER_OPENS { while let Some(project_paths) = project_paths_rx.next().await {
let mut match_rx = match_rx.clone(); let buffers = this.update(&mut cx, |this, cx| {
let tx = tx.clone(); project_paths
cx.spawn(|this, mut cx| async move { .into_iter()
while let Some(project_path) = match_rx.next().await { .map(|project_path| this.open_buffer(project_path, cx))
let buffer = this .collect::<Vec<_>>()
.update(&mut cx, |this, cx| this.open_buffer(project_path, cx))? })?;
.await for buffer_task in buffers {
.log_err(); if let Some(buffer) = buffer_task.await.log_err() {
if let Some(buffer) = buffer { if tx.send(buffer).await.is_err() {
tx.send_blocking(buffer).ok(); println!("other end dropped, returning");
return anyhow::Ok(());
}
} }
} }
anyhow::Ok(()) }
}) anyhow::Ok(())
.detach(); })
} .detach();
rx rx
} }
@@ -833,13 +840,9 @@ impl BufferStore {
query: &SearchQuery, query: &SearchQuery,
cx: &ModelContext<Self>, cx: &ModelContext<Self>,
) -> Vec<Model<Buffer>> { ) -> Vec<Model<Buffer>> {
let include_root = self let worktree_count = self.worktree_store.read(cx).visible_worktrees(cx).count();
.worktree_store let include_root = worktree_count > 1;
.read(cx)
.visible_worktrees(cx)
.collect::<Vec<_>>()
.len()
> 1;
self.buffers() self.buffers()
.filter_map(|buffer| { .filter_map(|buffer| {
let handle = buffer.clone(); let handle = buffer.clone();

View File

@@ -7275,6 +7275,7 @@ impl Project {
query: SearchQuery, query: SearchQuery,
cx: &mut ModelContext<Self>, cx: &mut ModelContext<Self>,
) -> Receiver<SearchResult> { ) -> Receiver<SearchResult> {
let start = std::time::Instant::now();
let (result_tx, result_rx) = smol::channel::bounded(1024); let (result_tx, result_rx) = smol::channel::bounded(1024);
let matching_buffers_rx = let matching_buffers_rx =
@@ -7343,6 +7344,7 @@ impl Project {
result_tx.send(SearchResult::LimitReached).await?; result_tx.send(SearchResult::LimitReached).await?;
} }
println!("search took: {:?}", start.elapsed());
anyhow::Ok(()) anyhow::Ok(())
}) })
.detach(); .detach();

View File

@@ -276,7 +276,7 @@ impl WorktreeStore {
fs: Arc<dyn Fs>, fs: Arc<dyn Fs>,
cx: &ModelContext<Self>, cx: &ModelContext<Self>,
) -> Receiver<ProjectPath> { ) -> Receiver<ProjectPath> {
let (matching_paths_tx, matching_paths_rx) = smol::channel::bounded(1024); let (matching_paths_tx, matching_paths_rx) = smol::channel::unbounded();
let snapshots = self let snapshots = self
.visible_worktrees(cx) .visible_worktrees(cx)
.filter_map(|tree| { .filter_map(|tree| {

View File

@@ -4761,6 +4761,12 @@ impl BackgroundScanner {
request.relative_paths.extend(next_request.relative_paths); request.relative_paths.extend(next_request.relative_paths);
request.done.extend(next_request.done); request.done.extend(next_request.done);
} }
if request.relative_paths.len() > 1 {
println!(
"------------------- Batched {} files",
request.relative_paths.len()
);
}
Ok(request) Ok(request)
} }
} }