#[non_exhaustive]pub struct RuntimeMetrics {
pub workers_count: usize,
pub total_park_count: u64,
pub max_park_count: u64,
pub min_park_count: u64,
pub total_busy_duration: Duration,
pub max_busy_duration: Duration,
pub min_busy_duration: Duration,
pub global_queue_depth: usize,
pub elapsed: Duration,
}Expand description
Key runtime metrics.
Fields (Non-exhaustive)§
This struct is marked as non-exhaustive
Struct { .. } syntax; cannot be matched against without a wildcard ..; and struct update syntax will not work.workers_count: usizeThe number of worker threads used by the runtime.
This metric is static for a runtime.
This metric is always equal to tokio::runtime::RuntimeMetrics::num_workers.
When using the current_thread runtime, the return value is always 1.
The number of workers is set by configuring
worker_threads with
tokio::runtime::Builder, or by parameterizing tokio::main.
§Examples
In the below example, the number of workers is set by parameterizing tokio::main:
use tokio::runtime::Handle;
#[tokio::main(flavor = "multi_thread", worker_threads = 10)]
async fn main() {
let handle = tokio::runtime::Handle::current();
let monitor = tokio_metrics::RuntimeMonitor::new(&handle);
let mut intervals = monitor.intervals();
let mut next_interval = || intervals.next().unwrap();
assert_eq!(next_interval().workers_count, 10);
}When using the current_thread runtime, the return value is always 1; e.g.:
use tokio::runtime::Handle;
#[tokio::main(flavor = "current_thread")]
async fn main() {
let handle = tokio::runtime::Handle::current();
let monitor = tokio_metrics::RuntimeMonitor::new(&handle);
let mut intervals = monitor.intervals();
let mut next_interval = || intervals.next().unwrap();
assert_eq!(next_interval().workers_count, 1);
}This metric is always equal to tokio::runtime::RuntimeMetrics::num_workers; e.g.:
use tokio::runtime::Handle;
#[tokio::main]
async fn main() {
let handle = Handle::current();
let monitor = tokio_metrics::RuntimeMonitor::new(&handle);
let mut intervals = monitor.intervals();
let mut next_interval = || intervals.next().unwrap();
assert_eq!(next_interval().workers_count, handle.metrics().num_workers());
}total_park_count: u64The number of times worker threads parked.
The worker park count increases by one each time the worker parks the thread waiting for new inbound events to process. This usually means the worker has processed all pending work and is currently idle.
§Definition
This metric is derived from the sum of tokio::runtime::RuntimeMetrics::worker_park_count
across all worker threads.
§See also
§Examples
#[tokio::main(flavor = "multi_thread", worker_threads = 2)]
async fn main() {
let handle = tokio::runtime::Handle::current();
let monitor = tokio_metrics::RuntimeMonitor::new(&handle);
let mut intervals = monitor.intervals();
let mut next_interval = || intervals.next().unwrap();
let interval = next_interval(); // end of interval 1
assert_eq!(interval.total_park_count, 0);
induce_parks().await;
let interval = next_interval(); // end of interval 2
assert!(interval.total_park_count >= 1); // usually 1 or 2 parks
}
async fn induce_parks() {
let _ = tokio::time::timeout(std::time::Duration::ZERO, async {
loop { tokio::task::yield_now().await; }
}).await;
}max_park_count: u64The maximum number of times any worker thread parked.
§Definition
This metric is derived from the maximum of
tokio::runtime::RuntimeMetrics::worker_park_count across all worker threads.
§See also
min_park_count: u64The minimum number of times any worker thread parked.
§Definition
This metric is derived from the maximum of
tokio::runtime::RuntimeMetrics::worker_park_count across all worker threads.
§See also
total_busy_duration: DurationThe amount of time worker threads were busy.
The worker busy duration increases whenever the worker is spending time processing work. Using this value can indicate the total load of workers.
§Definition
This metric is derived from the sum of
tokio::runtime::RuntimeMetrics::worker_total_busy_duration across all worker threads.
§See also
§Examples
In the below example, tasks spend a total of 3s busy:
use tokio::time::Duration;
fn main() {
let start = tokio::time::Instant::now();
let rt = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.unwrap();
let handle = rt.handle();
let monitor = tokio_metrics::RuntimeMonitor::new(&handle);
let mut intervals = monitor.intervals();
let mut next_interval = || intervals.next().unwrap();
let delay_1s = Duration::from_secs(1);
let delay_3s = Duration::from_secs(3);
rt.block_on(async {
// keep the main task busy for 1s
spin_for(delay_1s);
// spawn a task and keep it busy for 2s
let _ = tokio::spawn(async move {
spin_for(delay_3s);
}).await;
});
// flush metrics
drop(rt);
let elapsed = start.elapsed();
let interval = next_interval(); // end of interval 2
assert!(interval.total_busy_duration >= delay_1s + delay_3s);
assert!(interval.total_busy_duration <= elapsed);
}
fn time<F>(task: F) -> Duration
where
F: Fn() -> ()
{
let start = tokio::time::Instant::now();
task();
start.elapsed()
}
/// Block the current thread for a given `duration`.
fn spin_for(duration: Duration) {
let start = tokio::time::Instant::now();
while start.elapsed() <= duration {}
}Busy times may not accumulate as the above example suggests (FIXME: Why?); e.g., if we remove the three second delay, the time spent busy falls to mere microseconds:
use tokio::time::Duration;
fn main() {
let rt = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.unwrap();
let handle = rt.handle();
let monitor = tokio_metrics::RuntimeMonitor::new(&handle);
let mut intervals = monitor.intervals();
let mut next_interval = || intervals.next().unwrap();
let delay_1s = Duration::from_secs(1);
let elapsed = time(|| rt.block_on(async {
// keep the main task busy for 1s
spin_for(delay_1s);
}));
// flush metrics
drop(rt);
let interval = next_interval(); // end of interval 2
assert!(interval.total_busy_duration >= delay_1s); // FAIL
assert!(interval.total_busy_duration <= elapsed);
}
fn time<F>(task: F) -> Duration
where
F: Fn() -> ()
{
let start = tokio::time::Instant::now();
task();
start.elapsed()
}
/// Block the current thread for a given `duration`.
fn spin_for(duration: Duration) {
let start = tokio::time::Instant::now();
while start.elapsed() <= duration {}
}max_busy_duration: DurationThe maximum amount of time a worker thread was busy.
§Definition
This metric is derived from the maximum of
tokio::runtime::RuntimeMetrics::worker_total_busy_duration across all worker threads.
§See also
min_busy_duration: DurationThe minimum amount of time a worker thread was busy.
§Definition
This metric is derived from the minimum of
tokio::runtime::RuntimeMetrics::worker_total_busy_duration across all worker threads.
§See also
global_queue_depth: usizeThe number of tasks currently scheduled in the runtime’s global queue.
Tasks that are spawned or notified from a non-runtime thread are scheduled using the runtime’s global queue. This metric returns the current number of tasks pending in the global queue. As such, the returned value may increase or decrease as new tasks are scheduled and processed.
§Definition
This metric is derived from tokio::runtime::RuntimeMetrics::global_queue_depth.
§Example
let handle = runtime.handle().clone();
let monitor = tokio_metrics::RuntimeMonitor::new(&handle);
let mut intervals = monitor.intervals();
let mut next_interval = || intervals.next().unwrap();
let interval = next_interval(); // end of interval 1
assert_eq!(interval.num_remote_schedules, 0);
// spawn a system thread outside of the runtime
std::thread::spawn(move || {
// spawn two tasks from this non-runtime thread
handle.spawn(async {});
handle.spawn(async {});
}).join().unwrap();
// flush metrics
drop(runtime);
let interval = next_interval(); // end of interval 2
assert_eq!(interval.num_remote_schedules, 2);elapsed: DurationTotal amount of time elapsed since observing runtime metrics.
Implementations§
Source§impl RuntimeMetrics
impl RuntimeMetrics
Sourcepub fn busy_ratio(&self) -> f64
pub fn busy_ratio(&self) -> f64
Returns the ratio of the RuntimeMetrics::total_busy_duration to the RuntimeMetrics::elapsed.
Trait Implementations§
Source§impl Clone for RuntimeMetrics
impl Clone for RuntimeMetrics
Source§fn clone(&self) -> RuntimeMetrics
fn clone(&self) -> RuntimeMetrics
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more