Skip to content

Commit d636b84

Browse files
committed
tokio: optimize taskdumps when waiting for dump result
Don't just repeatedly yield the thread; wait for it to be notified. ref: tokio-rs#5717 (comment)
1 parent 4d97e1c commit d636b84

File tree

3 files changed

+25
-15
lines changed

3 files changed

+25
-15
lines changed

tokio/src/runtime/handle.rs

+9-6
Original file line numberDiff line numberDiff line change
@@ -349,24 +349,27 @@ cfg_taskdump! {
349349
// perform the trace in a separate thread so that the
350350
// trace itself does not appear in the taskdump.
351351
let handle = handle.clone();
352-
spawn_thread(|| {
352+
spawn_thread(async {
353353
let handle = handle;
354-
handle.dump()
354+
handle.dump().await
355355
}).await
356356
},
357357
}
358358
}
359359
}
360360

361361
/// Spawn a new thread and asynchronously await on its result.
362-
async fn spawn_thread<F, T>(f: F) -> T
362+
async fn spawn_thread<F>(f: F) -> <F as Future>::Output
363363
where
364-
F: FnOnce() -> T + Send + 'static,
365-
T: Send + 'static
364+
F: Future + Send + 'static,
365+
<F as Future>::Output: Send + 'static
366366
{
367367
let (tx, rx) = crate::sync::oneshot::channel();
368368
crate::loom::thread::spawn(|| {
369-
let _ = tx.send(f());
369+
let rt = crate::runtime::Builder::new_current_thread().build().unwrap();
370+
rt.block_on(async {
371+
let _ = tx.send(f.await);
372+
});
370373
});
371374
rx.await.unwrap()
372375
}

tokio/src/runtime/scheduler/multi_thread/handle.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -97,23 +97,23 @@ cfg_metrics! {
9797

9898
cfg_taskdump! {
9999
impl Handle {
100-
pub(crate) fn dump(&self) -> crate::runtime::Dump {
100+
pub(crate) async fn dump(&self) -> crate::runtime::Dump {
101101
let trace_status = &self.shared.trace_status;
102102

103103
// If a dump is in progress, block.
104-
trace_status.start_trace_request(&self);
104+
trace_status.start_trace_request(&self).await;
105105

106106
let result = loop {
107107
if let Some(result) = trace_status.take_result() {
108108
break result;
109109
} else {
110110
self.notify_all();
111-
crate::loom::thread::yield_now();
111+
trace_status.result_ready.notified().await;
112112
}
113113
};
114114

115115
// Allow other queued dumps to proceed.
116-
trace_status.end_trace_request(&self);
116+
trace_status.end_trace_request(&self).await;
117117

118118
result
119119
}

tokio/src/runtime/scheduler/multi_thread/worker.rs

+12-5
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ cfg_taskdump! {
214214
pub(super) trace_requested: AtomicBool,
215215
trace_start: Barrier,
216216
trace_end: Barrier,
217+
pub(super) result_ready: crate::sync::Notify,
217218
pub(super) trace_result: Mutex<Option<Dump>>,
218219
}
219220

@@ -223,6 +224,7 @@ cfg_taskdump! {
223224
trace_requested: AtomicBool::new(false),
224225
trace_start: Barrier::new(remotes_len),
225226
trace_end: Barrier::new(remotes_len),
227+
result_ready: crate::sync::Notify::new(),
226228
trace_result: Mutex::new(None),
227229
}
228230
}
@@ -231,29 +233,34 @@ cfg_taskdump! {
231233
self.trace_requested.load(Ordering::Relaxed)
232234
}
233235

234-
pub(super) fn start_trace_request(&self, handle: &Handle) {
236+
pub(super) async fn start_trace_request(&self, handle: &Handle) {
235237
while self.trace_requested.compare_exchange(false,
236238
true,
237239
Ordering::Acquire,
238240
Ordering::Relaxed).is_err()
239241
{
240242
handle.notify_all();
241-
crate::loom::thread::yield_now();
243+
crate::task::yield_now().await;
242244
}
243245
}
244246

247+
fn stash_result(&self, dump: Dump) {
248+
let _ = self.trace_result.lock().insert(dump);
249+
self.result_ready.notify_one();
250+
}
251+
245252
pub(super) fn take_result(&self) -> Option<Dump> {
246253
self.trace_result.lock().take()
247254
}
248255

249-
pub(super) fn end_trace_request(&self, handle: &Handle) {
256+
pub(super) async fn end_trace_request(&self, handle: &Handle) {
250257
while self.trace_requested.compare_exchange(true,
251258
false,
252259
Ordering::Acquire,
253260
Ordering::Relaxed).is_err()
254261
{
255262
handle.notify_all();
256-
crate::loom::thread::yield_now();
263+
crate::task::yield_now().await;
257264
}
258265
}
259266
}
@@ -1121,7 +1128,7 @@ impl Handle {
11211128
let result = dump::Dump::new(traces);
11221129

11231130
// stash the result
1124-
let _ = self.shared.trace_status.trace_result.lock().insert(result);
1131+
self.shared.trace_status.stash_result(result);
11251132

11261133
// allow other workers to proceed
11271134
self.shared.trace_status.trace_end.wait();

0 commit comments

Comments
 (0)