editor: Limit the amount of git processes spawned per multibuffer (#41472)

Lukas Wirth created

Release Notes:

- Reduced the number of concurrent git processes spawned for blaming

Change summary

crates/editor/src/git/blame.rs |  9 +++++++--
crates/git/src/repository.rs   | 23 +++++++++++------------
2 files changed, 18 insertions(+), 14 deletions(-)

Detailed changes

crates/editor/src/git/blame.rs 🔗

@@ -1,6 +1,7 @@
 use crate::Editor;
 use anyhow::Result;
 use collections::HashMap;
+use futures::StreamExt;
 use git::{
     GitHostingProviderRegistry, GitRemote, Oid,
     blame::{Blame, BlameEntry, ParsedCommitMessage},
@@ -507,7 +508,7 @@ impl GitBlame {
                     let buffer_edits = buffer.update(cx, |buffer, _| buffer.subscribe());
 
                     let blame_buffer = project.blame_buffer(&buffer, None, cx);
-                    Some((id, snapshot, buffer_edits, blame_buffer))
+                    Some(async move { (id, snapshot, buffer_edits, blame_buffer.await) })
                 })
                 .collect::<Vec<_>>()
         });
@@ -517,10 +518,14 @@ impl GitBlame {
             let (result, errors) = cx
                 .background_spawn({
                     async move {
+                        let blame = futures::stream::iter(blame)
+                            .buffered(4)
+                            .collect::<Vec<_>>()
+                            .await;
                         let mut res = vec![];
                         let mut errors = vec![];
                         for (id, snapshot, buffer_edits, blame) in blame {
-                            match blame.await {
+                            match blame {
                                 Ok(Some(Blame {
                                     entries,
                                     messages,

crates/git/src/repository.rs 🔗

@@ -1279,18 +1279,17 @@ impl GitRepository for RealGitRepository {
             .remote_url("upstream")
             .or_else(|| self.remote_url("origin"));
 
-        self.executor
-            .spawn(async move {
-                crate::blame::Blame::for_path(
-                    &git_binary_path,
-                    &working_directory?,
-                    &path,
-                    &content,
-                    remote_url,
-                )
-                .await
-            })
-            .boxed()
+        async move {
+            crate::blame::Blame::for_path(
+                &git_binary_path,
+                &working_directory?,
+                &path,
+                &content,
+                remote_url,
+            )
+            .await
+        }
+        .boxed()
     }
 
     fn diff(&self, diff: DiffType) -> BoxFuture<'_, Result<String>> {