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:
<img width="607" height="154" alt="image"
src="https://github.com/user-attachments/assets/4f9d9041-6209-426f-be44-f28449504c80"
/>

after:
<img width="632" height="121" alt="image"
src="https://github.com/user-attachments/assets/43b349f3-7685-4786-af1e-2a640cdf8ccd"
/>


Release Notes:

- N/A

---------

Co-authored-by: Anthony Eid <56899983+Anthony-Eid@users.noreply.github.com>
Co-authored-by: Anthony Eid <anthony@zed.dev>
This commit is contained in:
authored and GitHub committed 2026-04-28 08:29:21 +00:00
1 parent 55adf85aa7
commit 03c8df3547
1 file changed
+39 -8
+39 -8
View File
@@ -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<Oid>,
) -> Option<Oid> {
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));
}
}
}
}