Send buffer operations in batches to reduce latency

Co-Authored-By: Max Brunsfeld <max@zed.dev>
This commit is contained in:
Antonio Scandurra 2023-04-17 19:15:07 +02:00 committed by Max Brunsfeld
parent e655a6c767
commit 1f284408a9

View file

@ -1733,13 +1733,19 @@ impl Project {
async fn send_buffer_messages( async fn send_buffer_messages(
this: WeakModelHandle<Self>, this: WeakModelHandle<Self>,
mut rx: UnboundedReceiver<BufferMessage>, rx: UnboundedReceiver<BufferMessage>,
mut cx: AsyncAppContext, mut cx: AsyncAppContext,
) { ) -> Option<()> {
const MAX_BATCH_SIZE: usize = 128;
let mut needs_resync_with_host = false; let mut needs_resync_with_host = false;
while let Some(change) = rx.next().await { let mut operations_by_buffer_id = HashMap::default();
if let Some(this) = this.upgrade(&mut cx) { let mut changes = rx.ready_chunks(MAX_BATCH_SIZE);
let is_local = this.read_with(&cx, |this, _| this.is_local()); while let Some(changes) = changes.next().await {
let this = this.upgrade(&mut cx)?;
let is_local = this.read_with(&cx, |this, _| this.is_local());
for change in changes {
match change { match change {
BufferMessage::Operation { BufferMessage::Operation {
buffer_id, buffer_id,
@ -1748,21 +1754,14 @@ impl Project {
if needs_resync_with_host { if needs_resync_with_host {
continue; continue;
} }
let request = this.read_with(&cx, |this, _| {
let project_id = this.remote_id()?; operations_by_buffer_id
Some(this.client.request(proto::UpdateBuffer { .entry(buffer_id)
buffer_id, .or_insert(Vec::new())
project_id, .push(operation);
operations: vec![operation],
}))
});
if let Some(request) = request {
if request.await.is_err() && !is_local {
needs_resync_with_host = true;
}
}
} }
BufferMessage::Resync => { BufferMessage::Resync => {
operations_by_buffer_id.clear();
if this if this
.update(&mut cx, |this, cx| this.synchronize_remote_buffers(cx)) .update(&mut cx, |this, cx| this.synchronize_remote_buffers(cx))
.await .await
@ -1772,10 +1771,27 @@ impl Project {
} }
} }
} }
} else { }
break;
for (buffer_id, operations) in operations_by_buffer_id.drain() {
let request = this.read_with(&cx, |this, _| {
let project_id = this.remote_id()?;
Some(this.client.request(proto::UpdateBuffer {
buffer_id,
project_id,
operations,
}))
});
if let Some(request) = request {
if request.await.is_err() && !is_local {
needs_resync_with_host = true;
break;
}
}
} }
} }
None
} }
fn on_buffer_event( fn on_buffer_event(