From 3cbd7ccd485e921b79145fca3369287d3e19e8bd Mon Sep 17 00:00:00 2001 From: Levi Morrison Date: Thu, 12 Feb 2026 09:07:26 -0700 Subject: [PATCH] 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. --- profiling/src/profiling/thread_utils.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/profiling/src/profiling/thread_utils.rs b/profiling/src/profiling/thread_utils.rs index 52fabe629d..d52c62cec3 100644 --- a/profiling/src/profiling/thread_utils.rs +++ b/profiling/src/profiling/thread_utils.rs @@ -1,5 +1,4 @@ use crate::SAPI; -use libc::sched_yield; use std::cell::OnceCell; use std::mem::MaybeUninit; use std::thread::JoinHandle; @@ -59,6 +58,8 @@ pub struct TimeoutError { timeout_ms: u128, } +const JOIN_POLL_INTERVAL: Duration = Duration::from_millis(100); + /// Waits for the handle to be finished. If finished, it will join the handle. /// Otherwise, it will leak the handle and return an error. /// # Panics @@ -69,15 +70,18 @@ pub fn join_timeout(handle: JoinHandle<()>, timeout: Duration) -> Result<(), Tim // correct way to do this, but we've observed this can panic: // https://github.com/DataDog/dd-trace-php/issues/1919 // Thus far, we have not been able to reproduce it and address the root - // cause. So, for now, mitigate it instead with a busy loop. + // cause. So, for now, mitigate it instead with a loop. let start = Instant::now(); while !handle.is_finished() { - unsafe { sched_yield() }; - if start.elapsed() >= timeout { + let elapsed = start.elapsed(); + if elapsed >= timeout { let thread = handle.thread().name().unwrap_or("{unknown}").to_string(); let timeout_ms = timeout.as_millis(); return Err(TimeoutError { thread, timeout_ms }); } + + let remaining = timeout.saturating_sub(elapsed); + std::thread::sleep(std::cmp::min(JOIN_POLL_INTERVAL, remaining)); } if let Err(err) = handle.join() {