tokio: Add initial time driver metrics

This commit is contained in:
Lucio Franco
2022-02-24 19:53:08 +00:00
parent 769fb1547f
commit 748b785f19
8 changed files with 106 additions and 1 deletions
+5
View File
@@ -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! {
+24
View File
@@ -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)
}
}
}
+20
View File
@@ -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);
}
}
+4
View File
@@ -191,6 +191,10 @@ cfg_metrics! {
cfg_net! {
pub(crate) use metrics::IoDriverMetrics;
}
cfg_time! {
pub(crate) use metrics::TimerDriverMetrics;
}
}
cfg_not_metrics! {
+5 -1
View File
@@ -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! {
+15
View File
@@ -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;
}
}
+10
View File
@@ -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(),
}
}
+23
View File
@@ -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()