diff --git a/Cargo.lock b/Cargo.lock index 082f420f11f12968dd5c6bec46c3fab4f2b37a7f..9dc5c45f34ba38da75c6223fee4e901e8877a7d4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7129,6 +7129,7 @@ dependencies = [ "serde", "serde_json", "settings", + "smol", "strum 0.27.2", "telemetry", "theme", diff --git a/crates/git_ui/Cargo.toml b/crates/git_ui/Cargo.toml index 326424f28d46c9802439293165eae9708d63b064..8ac2f318e46bb114fae151db99427a80eaba61b0 100644 --- a/crates/git_ui/Cargo.toml +++ b/crates/git_ui/Cargo.toml @@ -50,6 +50,7 @@ schemars.workspace = true serde.workspace = true serde_json.workspace = true settings.workspace = true +smol.workspace = true strum.workspace = true telemetry.workspace = true theme.workspace = true diff --git a/crates/git_ui/src/project_diff.rs b/crates/git_ui/src/project_diff.rs index a6de68b789c33ff75b8e6f474f31b7f9f6d8399c..515056bef48889ecc4da5c3f3f1a8983f9d56841 100644 --- a/crates/git_ui/src/project_diff.rs +++ b/crates/git_ui/src/project_diff.rs @@ -32,6 +32,7 @@ use project::{ }, }; use settings::{Settings, SettingsStore}; +use smol::future::yield_now; use std::any::{Any, TypeId}; use std::ops::Range; use std::sync::Arc; @@ -584,6 +585,9 @@ impl ProjectDiff { for (entry, path_key) in buffers_to_load.into_iter().zip(path_keys.into_iter()) { if let Some((buffer, diff)) = entry.load.await.log_err() { + // We might be lagging behind enough that all future entry.load futures are no longer pending. + // If that is the case, this task will never yield, starving the foreground thread of execution time. + yield_now().await; cx.update(|window, cx| { this.update(cx, |this, cx| { this.register_buffer(path_key, entry.file_status, buffer, diff, window, cx) diff --git a/crates/project/src/git_store.rs b/crates/project/src/git_store.rs index a2efc12e52de64da8c796ee3fa38acd19fd05ac5..d0888d969303fdf67776243ab426289b25f10a7e 100644 --- a/crates/project/src/git_store.rs +++ b/crates/project/src/git_store.rs @@ -56,6 +56,7 @@ use rpc::{ }; use serde::Deserialize; use settings::WorktreeId; +use smol::future::yield_now; use std::{ cmp::Ordering, collections::{BTreeSet, HashSet, VecDeque}, @@ -2984,6 +2985,10 @@ impl BufferGitState { ); } + // Dropping BufferDiff can be expensive, so yield back to the event loop + // for a bit + yield_now().await; + let mut new_uncommitted_diff = None; if let Some(uncommitted_diff) = &uncommitted_diff { new_uncommitted_diff = if index_matches_head { @@ -3005,6 +3010,10 @@ impl BufferGitState { } } + // Dropping BufferDiff can be expensive, so yield back to the event loop + // for a bit + yield_now().await; + let cancel = this.update(cx, |this, _| { // This checks whether all pending stage/unstage operations // have quiesced (i.e. both the corresponding write and the @@ -3043,6 +3052,8 @@ impl BufferGitState { None }; + yield_now().await; + if let Some((uncommitted_diff, new_uncommitted_diff)) = uncommitted_diff.as_ref().zip(new_uncommitted_diff.clone()) {