Limit project search to avoid unresponsive app (#9404)
This fixes #[#9135](https://github.com/zed-industries/zed/issues/9135) by introducing file/results limit to project search. It does this by changing how project search works in multiple ways. User-facing changes: - Number files that are being searched is now limited to 5000 - Number of search results in all files is now limited to 10000 - If a limit is reached, search is stopped and a message is displayed to the user Under the hood, we also reworked `Project::search_local`: - Code has been refactored so that the concurrency-logic is easier to distinguish from the search logic. - We now limit the number of concurrent `open_buffer` operations, since that is being done on the main thread and can lead to beachballs when finding a lot of results. Note for reviewer: @SomeoneToIgnore since you know this code, can you take a look at this? The changes might look bigger than they are in certain places because I only extracted code into functions, but the middle part — the sorting of file paths — has changed in order to avoid too many tasks opening buffers at the same time and making app unresponsive. What's also curious is that I think there was a bug in that we searched ignored entries _twice_: once in `search_snapshots` and then later in the dedicated `search_ignored_entry` function. I changed the `entries()` call in `search_snapshots` so that it's always `false`, but that caused tests to fail (see `test_search_in_gitignored_dirs`). @bennetbo and I think that there's some state in the Project that made the tests pass before, because the last of the 3 assertions in that test only passes when the other two queries run. So we changed the test to be more stateless and included the possible fix in `search_snapshots`. Release Notes: - Fixed project-wide search leading to unresponsive application when searching in ignored files, by limiting the number of files that are searched (to 5000) and the number of overall search results to 10000. Additional performance improvements have also been made in order to offload more work onto a background thread. ([#9135](https://github.com/zed-industries/zed/issues/9135)). --------- Co-authored-by: Antonio Scandurra <antonio@zed.dev> Co-authored-by: Bennet <bennetbo@gmx.de>
This commit is contained in:
parent
52a9bc3e1b
commit
a69eddc081
6 changed files with 373 additions and 357 deletions
|
@ -20,6 +20,7 @@ use live_kit_client::MacOSDisplay;
|
|||
use lsp::LanguageServerId;
|
||||
use project::{
|
||||
search::SearchQuery, DiagnosticSummary, FormatTrigger, HoverBlockKind, Project, ProjectPath,
|
||||
SearchResult,
|
||||
};
|
||||
use rand::prelude::*;
|
||||
use serde_json::json;
|
||||
|
@ -4772,8 +4773,15 @@ async fn test_project_search(
|
|||
cx,
|
||||
)
|
||||
});
|
||||
while let Some((buffer, ranges)) = search_rx.next().await {
|
||||
results.entry(buffer).or_insert(ranges);
|
||||
while let Some(result) = search_rx.next().await {
|
||||
match result {
|
||||
SearchResult::Buffer { buffer, ranges } => {
|
||||
results.entry(buffer).or_insert(ranges);
|
||||
}
|
||||
SearchResult::LimitReached => {
|
||||
panic!("Unexpectedly reached search limit in tests. If you do want to assert limit-reached, change this panic call.")
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
let mut ranges_by_path = results
|
||||
|
|
|
@ -13,7 +13,7 @@ use language::{
|
|||
};
|
||||
use lsp::FakeLanguageServer;
|
||||
use pretty_assertions::assert_eq;
|
||||
use project::{search::SearchQuery, Project, ProjectPath};
|
||||
use project::{search::SearchQuery, Project, ProjectPath, SearchResult};
|
||||
use rand::{
|
||||
distributions::{Alphanumeric, DistString},
|
||||
prelude::*,
|
||||
|
@ -879,8 +879,10 @@ impl RandomizedTest for ProjectCollaborationTest {
|
|||
drop(project);
|
||||
let search = cx.executor().spawn(async move {
|
||||
let mut results = HashMap::default();
|
||||
while let Some((buffer, ranges)) = search.next().await {
|
||||
results.entry(buffer).or_insert(ranges);
|
||||
while let Some(result) = search.next().await {
|
||||
if let SearchResult::Buffer { buffer, ranges } = result {
|
||||
results.entry(buffer).or_insert(ranges);
|
||||
}
|
||||
}
|
||||
results
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue