mirror of
https://github.com/tokio-rs/tokio.git
synced 2026-08-28 00:00:11 +02:00
tokio: Add initial time driver metrics
This commit is contained in:
@@ -26,6 +26,11 @@ cfg_metrics! {
|
||||
mod io;
|
||||
pub(crate) use io::IoDriverMetrics;
|
||||
}
|
||||
|
||||
cfg_time! {
|
||||
mod time;
|
||||
pub(crate) use time::TimerDriverMetrics;
|
||||
}
|
||||
}
|
||||
|
||||
cfg_not_metrics! {
|
||||
|
||||
@@ -534,3 +534,27 @@ cfg_net! {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cfg_time! {
|
||||
impl RuntimeMetrics {
|
||||
/// Returns the number of timer entries currently tracked by the
|
||||
/// runtime's timer driver.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use tokio::runtime::Handle;
|
||||
///
|
||||
/// #[tokio::main]
|
||||
/// async fn main() {
|
||||
/// let metrics = Handle::current().metrics();
|
||||
///
|
||||
/// let n = metrics.time_driver_entry_count();
|
||||
/// println!("{} timer entries currently tracked by the runtime's time driver.", n);
|
||||
/// }
|
||||
/// ```
|
||||
pub fn time_driver_entry_count(&self) -> u64 {
|
||||
self.handle.time_handle.as_ref().map(|h| h.metrics().entry_count.load(Relaxed)).unwrap_or(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
use std::sync::atomic::{AtomicU64, Ordering::Relaxed};
|
||||
|
||||
#[derive(Default)]
|
||||
pub(crate) struct TimerDriverMetrics {
|
||||
pub(super) entry_count: AtomicU64,
|
||||
}
|
||||
|
||||
impl TimerDriverMetrics {
|
||||
pub(crate) fn incr_entry_count(&self) {
|
||||
let prev = self.entry_count.load(Relaxed);
|
||||
let new = prev.wrapping_add(1);
|
||||
self.entry_count.store(new, Relaxed);
|
||||
}
|
||||
|
||||
pub(crate) fn dec_entry_count(&self) {
|
||||
let prev = self.entry_count.load(Relaxed);
|
||||
let new = prev.wrapping_sub(1);
|
||||
self.entry_count.store(new, Relaxed);
|
||||
}
|
||||
}
|
||||
@@ -191,6 +191,10 @@ cfg_metrics! {
|
||||
cfg_net! {
|
||||
pub(crate) use metrics::IoDriverMetrics;
|
||||
}
|
||||
|
||||
cfg_time! {
|
||||
pub(crate) use metrics::TimerDriverMetrics;
|
||||
}
|
||||
}
|
||||
|
||||
cfg_not_metrics! {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::loom::sync::Arc;
|
||||
use crate::time::driver::ClockTime;
|
||||
use crate::time::driver::{ClockTime, TimerDriverMetrics};
|
||||
use std::fmt;
|
||||
|
||||
/// Handle to time driver instance.
|
||||
@@ -30,6 +30,10 @@ impl Handle {
|
||||
pub(super) fn is_shutdown(&self) -> bool {
|
||||
self.inner.is_shutdown()
|
||||
}
|
||||
|
||||
pub(crate) fn metrics(&self) -> &TimerDriverMetrics {
|
||||
&self.inner.metrics
|
||||
}
|
||||
}
|
||||
|
||||
cfg_rt! {
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
cfg_not_rt_and_metrics! {
|
||||
#[derive(Default)]
|
||||
pub(crate) struct TimerDriverMetrics {}
|
||||
|
||||
impl TimerDriverMetrics {
|
||||
pub(crate) fn incr_entry_count(&self) {}
|
||||
pub(crate) fn dec_entry_count(&self) {}
|
||||
}
|
||||
}
|
||||
|
||||
cfg_rt! {
|
||||
cfg_metrics! {
|
||||
pub(crate) use crate::runtime::TimerDriverMetrics;
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,9 @@ pub(crate) use self::handle::Handle;
|
||||
|
||||
mod wheel;
|
||||
|
||||
mod metrics;
|
||||
pub(self) use metrics::TimerDriverMetrics;
|
||||
|
||||
pub(super) mod sleep;
|
||||
|
||||
use crate::loom::sync::atomic::{AtomicBool, Ordering};
|
||||
@@ -148,6 +151,8 @@ struct Inner {
|
||||
|
||||
/// True if the driver is being shutdown.
|
||||
pub(super) is_shutdown: AtomicBool,
|
||||
|
||||
metrics: TimerDriverMetrics,
|
||||
}
|
||||
|
||||
/// Time state shared which must be protected by a `Mutex`
|
||||
@@ -357,6 +362,7 @@ impl Handle {
|
||||
let mut lock = self.get().lock();
|
||||
|
||||
if entry.as_ref().might_be_registered() {
|
||||
self.metrics().dec_entry_count();
|
||||
lock.wheel.remove(entry);
|
||||
}
|
||||
|
||||
@@ -377,6 +383,7 @@ impl Handle {
|
||||
// We may have raced with a firing/deregistration, so check before
|
||||
// deregistering.
|
||||
if unsafe { entry.as_ref().might_be_registered() } {
|
||||
self.metrics().dec_entry_count();
|
||||
lock.wheel.remove(entry);
|
||||
}
|
||||
|
||||
@@ -393,6 +400,8 @@ impl Handle {
|
||||
// the timer entry.
|
||||
match unsafe { lock.wheel.insert(entry) } {
|
||||
Ok(when) => {
|
||||
self.metrics().incr_entry_count();
|
||||
|
||||
if lock
|
||||
.next_wake
|
||||
.map(|next_wake| when < next_wake.get())
|
||||
@@ -504,6 +513,7 @@ impl Inner {
|
||||
wheel: wheel::Wheel::new(),
|
||||
}),
|
||||
is_shutdown: AtomicBool::new(false),
|
||||
metrics: TimerDriverMetrics::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -403,6 +403,29 @@ fn io_driver_ready_count() {
|
||||
assert_eq!(metrics.io_driver_ready_count(), 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn time_driver_entry_count() {
|
||||
use tokio::time::sleep;
|
||||
use tokio_test::task;
|
||||
|
||||
let rt = basic();
|
||||
let metrics = rt.metrics();
|
||||
|
||||
let _guard = rt.handle().enter();
|
||||
|
||||
assert_eq!(metrics.time_driver_entry_count(), 0);
|
||||
|
||||
let mut fut = task::spawn(sleep(Duration::from_secs(1_000)));
|
||||
|
||||
assert!(fut.poll().is_pending());
|
||||
|
||||
assert_eq!(metrics.time_driver_entry_count(), 1);
|
||||
|
||||
drop(fut);
|
||||
|
||||
assert_eq!(metrics.time_driver_entry_count(), 0);
|
||||
}
|
||||
|
||||
fn basic() -> Runtime {
|
||||
tokio::runtime::Builder::new_current_thread()
|
||||
.enable_all()
|
||||
|
||||
Reference in New Issue
Block a user