Skip to content

Commit 3cbd7cc

Browse files
committed
fix(profiling): reduce shutdown CPU
We've observed that we'll spend a good amount of CPU doing the busy loop, meaning the system decided not really to yield the CPU. Sleeping will actually yield the CPU, which increases the chance that the other thread will do its work. This is not particularly problematic. It's mostly annoying to see in the profiles when trying to identify areas to attack to reduce it.
1 parent cf7ba04 commit 3cbd7cc

1 file changed

Lines changed: 8 additions & 4 deletions

File tree

profiling/src/profiling/thread_utils.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use crate::SAPI;
2-
use libc::sched_yield;
32
use std::cell::OnceCell;
43
use std::mem::MaybeUninit;
54
use std::thread::JoinHandle;
@@ -59,6 +58,8 @@ pub struct TimeoutError {
5958
timeout_ms: u128,
6059
}
6160

61+
const JOIN_POLL_INTERVAL: Duration = Duration::from_millis(100);
62+
6263
/// Waits for the handle to be finished. If finished, it will join the handle.
6364
/// Otherwise, it will leak the handle and return an error.
6465
/// # Panics
@@ -69,15 +70,18 @@ pub fn join_timeout(handle: JoinHandle<()>, timeout: Duration) -> Result<(), Tim
6970
// correct way to do this, but we've observed this can panic:
7071
// https://github.com/DataDog/dd-trace-php/issues/1919
7172
// Thus far, we have not been able to reproduce it and address the root
72-
// cause. So, for now, mitigate it instead with a busy loop.
73+
// cause. So, for now, mitigate it instead with a loop.
7374
let start = Instant::now();
7475
while !handle.is_finished() {
75-
unsafe { sched_yield() };
76-
if start.elapsed() >= timeout {
76+
let elapsed = start.elapsed();
77+
if elapsed >= timeout {
7778
let thread = handle.thread().name().unwrap_or("{unknown}").to_string();
7879
let timeout_ms = timeout.as_millis();
7980
return Err(TimeoutError { thread, timeout_ms });
8081
}
82+
83+
let remaining = timeout.saturating_sub(elapsed);
84+
std::thread::sleep(std::cmp::min(JOIN_POLL_INTERVAL, remaining));
8185
}
8286

8387
if let Err(err) = handle.join() {

0 commit comments

Comments
 (0)