New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
remove frequent global is_shutdown flag check on timer operations #5301
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,6 +18,7 @@ pub(crate) use source::TimeSource; | |
|
||
mod wheel; | ||
|
||
#[cfg(feature = "test-util")] | ||
use crate::loom::sync::atomic::{AtomicBool, Ordering}; | ||
use crate::loom::sync::Mutex; | ||
use crate::runtime::driver::{self, IoHandle, IoStack}; | ||
|
@@ -93,9 +94,6 @@ struct Inner { | |
// The state is split like this so `Handle` can access `is_shutdown` without locking the mutex | ||
pub(super) state: Mutex<InnerState>, | ||
|
||
/// True if the driver is being shutdown. | ||
pub(super) is_shutdown: AtomicBool, | ||
Comment on lines
-96
to
-97
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't remember this being an atomic, and I assumed it wasn't when I made the comment that the time driver has a similar issue. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That makes sense. It's questionable that this change improves performance at all. TBH I have no idea how to benchmark timers only. |
||
|
||
// When `true`, a call to `park_timeout` should immediately return and time | ||
// should not advance. One reason for this to be `true` is if the task | ||
// passed to `Runtime::block_on` called `task::yield_now()`. | ||
|
@@ -116,6 +114,9 @@ struct InnerState { | |
|
||
/// Timer wheel. | ||
wheel: wheel::Wheel, | ||
|
||
/// True if the driver is being shutdown. | ||
is_shutdown: bool, | ||
} | ||
|
||
// ===== impl Driver ===== | ||
|
@@ -135,8 +136,8 @@ impl Driver { | |
elapsed: 0, | ||
next_wake: None, | ||
wheel: wheel::Wheel::new(), | ||
is_shutdown: false, | ||
}), | ||
is_shutdown: AtomicBool::new(false), | ||
|
||
#[cfg(feature = "test-util")] | ||
did_wake: AtomicBool::new(false), | ||
|
@@ -159,15 +160,17 @@ impl Driver { | |
pub(crate) fn shutdown(&mut self, rt_handle: &driver::Handle) { | ||
let handle = rt_handle.time(); | ||
|
||
if handle.is_shutdown() { | ||
return; | ||
} | ||
{ | ||
let mut lock = handle.inner.lock(); | ||
|
||
handle.inner.is_shutdown.store(true, Ordering::SeqCst); | ||
if lock.is_shutdown { | ||
return; | ||
} | ||
|
||
// Advance time forward to the end of time. | ||
lock.is_shutdown = true; | ||
} | ||
|
||
handle.process_at_time(u64::MAX); | ||
handle.process_at_time(None); | ||
|
||
self.park.shutdown(rt_handle); | ||
} | ||
|
@@ -176,7 +179,7 @@ impl Driver { | |
let handle = rt_handle.time(); | ||
let mut lock = handle.inner.state.lock(); | ||
|
||
assert!(!handle.is_shutdown()); | ||
assert!(!lock.is_shutdown); | ||
|
||
let next_wake = lock.wheel.next_expiration_time(); | ||
lock.next_wake = | ||
|
@@ -251,10 +254,16 @@ impl Handle { | |
pub(self) fn process(&self) { | ||
let now = self.time_source().now(); | ||
|
||
self.process_at_time(now) | ||
self.process_at_time(Some(now)) | ||
} | ||
|
||
pub(self) fn process_at_time(&self, mut now: u64) { | ||
pub(self) fn process_at_time(&self, now: Option<u64>) { | ||
let (mut now, state) = match now { | ||
Some(now) => (now, Ok(())), | ||
// Runtime being shutdown, advance time forward to the end of time. | ||
None => (u64::MAX, Err(Error::shutdown())), | ||
}; | ||
|
||
let mut waker_list: [Option<Waker>; 32] = Default::default(); | ||
let mut waker_idx = 0; | ||
|
||
|
@@ -274,7 +283,7 @@ impl Handle { | |
debug_assert!(unsafe { entry.is_pending() }); | ||
|
||
// SAFETY: We hold the driver lock, and just removed the entry from any linked lists. | ||
if let Some(waker) = unsafe { entry.fire(Ok(())) } { | ||
if let Some(waker) = unsafe { entry.fire(state) } { | ||
waker_list[waker_idx] = Some(waker); | ||
|
||
waker_idx += 1; | ||
|
@@ -354,8 +363,11 @@ impl Handle { | |
// Now that we have exclusive control of this entry, mint a handle to reinsert it. | ||
let entry = entry.as_ref().handle(); | ||
|
||
if self.is_shutdown() { | ||
unsafe { entry.fire(Err(crate::time::error::Error::shutdown())) } | ||
if lock.is_shutdown { | ||
unsafe { | ||
entry.set_expiration(0); | ||
entry.fire(Err(Error::shutdown())) | ||
} | ||
} else { | ||
entry.set_expiration(new_tick); | ||
|
||
|
@@ -405,11 +417,6 @@ impl Inner { | |
pub(super) fn lock(&self) -> crate::loom::sync::MutexGuard<'_, InnerState> { | ||
self.state.lock() | ||
} | ||
|
||
// Check whether the driver has been shutdown | ||
pub(super) fn is_shutdown(&self) -> bool { | ||
self.is_shutdown.load(Ordering::SeqCst) | ||
} | ||
} | ||
|
||
impl fmt::Debug for Inner { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems like you've also included a fix for #5082 here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems so, though I discovered the issue just now. During working on this issue I messed up more in this module and cleared up most of them but this line survived. If you think it's better to not mix #5082 here I'll revert it.