search: New old search implementation (#39956)
This is an in-progress work on changing how task scheduler affects performance of project search. Instead of relying on tasks being executed at a discretion of the task scheduler, we want to experiment with having a set of "agents" that prioritize driving in-progress project search matches to completion over pushing the whole thing to completion. This should hopefully significantly improve throughput & latency of project search. Release Notes: - Improved project search performance --------- Co-authored-by: Smit Barmase <smit@zed.dev> Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
This commit is contained in:
co-authored by
Smit Barmase
Smit Barmase
parent
85c2aa7325
commit
7c4fb5a899
@@ -1,14 +1,12 @@
|
||||
use crate::{
|
||||
ProjectItem as _, ProjectPath,
|
||||
ProjectPath,
|
||||
lsp_store::OpenLspBufferHandle,
|
||||
search::SearchQuery,
|
||||
worktree_store::{WorktreeStore, WorktreeStoreEvent},
|
||||
};
|
||||
use anyhow::{Context as _, Result, anyhow};
|
||||
use client::Client;
|
||||
use collections::{HashMap, HashSet, hash_map};
|
||||
use fs::Fs;
|
||||
use futures::{Future, FutureExt as _, StreamExt, channel::oneshot, future::Shared};
|
||||
use futures::{Future, FutureExt as _, channel::oneshot, future::Shared};
|
||||
use gpui::{
|
||||
App, AppContext as _, AsyncApp, Context, Entity, EventEmitter, Subscription, Task, WeakEntity,
|
||||
};
|
||||
@@ -23,8 +21,8 @@ use rpc::{
|
||||
AnyProtoClient, ErrorCode, ErrorExt as _, TypedEnvelope,
|
||||
proto::{self},
|
||||
};
|
||||
use smol::channel::Receiver;
|
||||
use std::{io, pin::pin, sync::Arc, time::Instant};
|
||||
|
||||
use std::{io, sync::Arc, time::Instant};
|
||||
use text::{BufferId, ReplicaId};
|
||||
use util::{ResultExt as _, TryFutureExt, debug_panic, maybe, rel_path::RelPath};
|
||||
use worktree::{File, PathChange, ProjectEntryId, Worktree, WorktreeId};
|
||||
@@ -972,6 +970,10 @@ impl BufferStore {
|
||||
.filter_map(|buffer| buffer.upgrade())
|
||||
}
|
||||
|
||||
pub(crate) fn is_searchable(&self, id: &BufferId) -> bool {
|
||||
!self.non_searchable_buffers.contains(&id)
|
||||
}
|
||||
|
||||
pub fn loading_buffers(
|
||||
&self,
|
||||
) -> impl Iterator<Item = (&ProjectPath, impl Future<Output = Result<Entity<Buffer>>>)> {
|
||||
@@ -1096,63 +1098,6 @@ impl BufferStore {
|
||||
Some(())
|
||||
}
|
||||
|
||||
pub fn find_search_candidates(
|
||||
&mut self,
|
||||
query: &SearchQuery,
|
||||
mut limit: usize,
|
||||
fs: Arc<dyn Fs>,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Receiver<Entity<Buffer>> {
|
||||
let (tx, rx) = smol::channel::unbounded();
|
||||
let mut open_buffers = HashSet::default();
|
||||
let mut unnamed_buffers = Vec::new();
|
||||
for handle in self.buffers() {
|
||||
let buffer = handle.read(cx);
|
||||
if self.non_searchable_buffers.contains(&buffer.remote_id()) {
|
||||
continue;
|
||||
} else if let Some(entry_id) = buffer.entry_id(cx) {
|
||||
open_buffers.insert(entry_id);
|
||||
} else {
|
||||
limit = limit.saturating_sub(1);
|
||||
unnamed_buffers.push(handle)
|
||||
};
|
||||
}
|
||||
|
||||
const MAX_CONCURRENT_BUFFER_OPENS: usize = 64;
|
||||
let project_paths_rx = self
|
||||
.worktree_store
|
||||
.update(cx, |worktree_store, cx| {
|
||||
worktree_store.find_search_candidates(query.clone(), limit, open_buffers, fs, cx)
|
||||
})
|
||||
.chunks(MAX_CONCURRENT_BUFFER_OPENS);
|
||||
|
||||
cx.spawn(async move |this, cx| {
|
||||
for buffer in unnamed_buffers {
|
||||
tx.send(buffer).await.ok();
|
||||
}
|
||||
|
||||
let mut project_paths_rx = pin!(project_paths_rx);
|
||||
while let Some(project_paths) = project_paths_rx.next().await {
|
||||
let buffers = this.update(cx, |this, cx| {
|
||||
project_paths
|
||||
.into_iter()
|
||||
.map(|project_path| this.open_buffer(project_path, cx))
|
||||
.collect::<Vec<_>>()
|
||||
})?;
|
||||
for buffer_task in buffers {
|
||||
if let Some(buffer) = buffer_task.await.log_err()
|
||||
&& tx.send(buffer).await.is_err()
|
||||
{
|
||||
return anyhow::Ok(());
|
||||
}
|
||||
}
|
||||
}
|
||||
anyhow::Ok(())
|
||||
})
|
||||
.detach();
|
||||
rx
|
||||
}
|
||||
|
||||
fn on_buffer_event(
|
||||
&mut self,
|
||||
buffer: Entity<Buffer>,
|
||||
|
||||
Reference in New Issue
Block a user