Skip to content

Commit d9bc0dc

Browse files
committed
Yield to the executor in the the Endpoint
As long as there is data to send or receive the `Endpoint` `Future` will currently continue to execute and thereby retain the eventloop. In order to allow other code to execute in between we yield back to the executor after each iteration. Instead of doing mulitiple iterations in one `EndpointDriver::poll` call we can just increase the maximum amount of packets to send or receive in a single iteration and pick a number which optimizes performance. Therefore the loop gets completely removed.
1 parent ec54b4e commit d9bc0dc

1 file changed

Lines changed: 16 additions & 11 deletions

File tree

quinn/src/endpoint.rs

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -200,28 +200,33 @@ where
200200

201201
#[allow(unused_mut)] // MSRV
202202
fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
203-
let endpoint = &mut *self.0.lock().unwrap();
203+
let mut endpoint = self.0.lock().unwrap();
204204
if endpoint.driver.is_none() {
205205
endpoint.driver = Some(cx.waker().clone());
206206
}
207-
loop {
208-
let now = Instant::now();
209-
let mut keep_going = false;
210-
keep_going |= endpoint.drive_recv(cx, now)?;
211-
endpoint.handle_events(cx);
212-
keep_going |= endpoint.drive_send(cx)?;
213-
if !keep_going {
214-
break;
215-
}
216-
}
207+
208+
let now = Instant::now();
209+
let mut keep_going = false;
210+
keep_going |= endpoint.drive_recv(cx, now)?;
211+
endpoint.handle_events(cx);
212+
keep_going |= endpoint.drive_send(cx)?;
213+
217214
if !endpoint.incoming.is_empty() {
218215
if let Some(task) = endpoint.incoming_reader.take() {
219216
task.wake();
220217
}
221218
}
219+
222220
if endpoint.ref_count == 0 && endpoint.connections.is_empty() {
223221
Poll::Ready(Ok(()))
224222
} else {
223+
drop(endpoint);
224+
// If there is more work to do schedule the endpoint task again.
225+
// `wake_by_ref()` is called outside the lock to minimize
226+
// lock contention on a multithreaded runtime.
227+
if keep_going {
228+
cx.waker().wake_by_ref();
229+
}
225230
Poll::Pending
226231
}
227232
}

0 commit comments

Comments
 (0)