From 03c8df354795efd7f1c75aba9c49f05c38bceb39 Mon Sep 17 00:00:00 2001 From: feeiyu <158308373+feeiyu@users.noreply.github.com> Date: Tue, 28 Apr 2026 16:29:21 +0800 Subject: [PATCH] git_graph: Align CommitDataReader with batched commit processing (#54600) Self-Review Checklist: - [X] I've reviewed my own diff for quality, security, and reliability - [ ] Unsafe blocks (if any) have justifying comments - [ ] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [ ] Tests cover the new/changed behavior - [X] Performance impact has been considered and is acceptable Updated `CommitDataReader::read` from single SHA to batched input/output. `run_commit_data_reader` is designed to process requests in batches, but `CommitDataReader::read` previously only sent one SHA per call. So in practice, commit data was effectively processed one-by-one from the caller path. The temporary debug logs show that batching was not performed previously. before: image after: image Release Notes: - N/A --------- Co-authored-by: Anthony Eid <56899983+Anthony-Eid@users.noreply.github.com> Co-authored-by: Anthony Eid --- crates/project/src/git_store.rs | 47 +++++++++++++++++++++++++++------ 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/crates/project/src/git_store.rs b/crates/project/src/git_store.rs index a6d963bd11..31ad970d6e 100644 --- a/crates/project/src/git_store.rs +++ b/crates/project/src/git_store.rs @@ -5236,6 +5236,16 @@ impl Repository { result_tx: smol::channel::Sender<(Oid, CommitData)>, background_executor: BackgroundExecutor, ) { + async fn receive_commit_data_request( + request_rx: &smol::channel::Receiver, + ) -> Option { + if request_rx.is_closed() && request_rx.is_empty() { + future::pending().await + } else { + request_rx.recv().await.ok() + } + } + let reader = match backend.commit_data_reader() { Ok(reader) => reader, Err(error) => { @@ -5244,19 +5254,38 @@ impl Repository { } }; + let read_commit_data = |sha| reader.read(sha).map(move |result| (sha, result)); + let mut read_futures = FuturesUnordered::new(); + loop { - let timeout = background_executor.timer(std::time::Duration::from_secs(10)); + if read_futures.is_empty() { + let timeout = background_executor.timer(Duration::from_secs(10)); + + futures::select_biased! { + sha = futures::FutureExt::fuse(receive_commit_data_request(&request_rx)) => { + if let Some(sha) = sha { + read_futures.push(read_commit_data(sha)); + } + } + _ = futures::FutureExt::fuse(timeout) => { + break; + } + } + } + + let next_read = read_futures.next().fuse(); + futures::pin_mut!(next_read); futures::select_biased! { - sha = futures::FutureExt::fuse(request_rx.recv()) => { - let Ok(sha) = sha else { - break; + result = next_read => { + let Some((sha, result)) = result else { + continue; }; - match reader.read(sha).await { + match result { Ok(commit_data) => { if result_tx.send((sha, commit_data)).await.is_err() { - break; + return; } } Err(error) => { @@ -5264,8 +5293,10 @@ impl Repository { } } } - _ = futures::FutureExt::fuse(timeout) => { - break; + sha = futures::FutureExt::fuse(receive_commit_data_request(&request_rx)) => { + if let Some(sha) = sha { + read_futures.push(read_commit_data(sha)); + } } } }