Skip to content

Commit 904c538

Browse files
authored
rt: add steal_operations metric (#37)
Follow-up to #35. The new metric is available starting with tokio v1.25.0.
1 parent 234690c commit 904c538

File tree

3 files changed

+108
-2
lines changed

3 files changed

+108
-2
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ futures = "0.3.21"
3131
num_cpus = "1.13.1"
3232
serde = { version = "1.0.136", features = ["derive"] }
3333
serde_json = "1.0.79"
34-
tokio = { version = "1.15.0", features = ["full", "rt", "time", "macros", "test-util"] }
34+
tokio = { version = "1.26.0", features = ["full", "rt", "time", "macros", "test-util"] }
3535

3636
[[example]]
3737
name = "runtime"

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,12 @@ tokio::spawn(do_work());
182182
The maximum number of tasks any worker thread stole from another worker thread.
183183
- **[`min_steal_count`]**
184184
The minimum number of tasks any worker thread stole from another worker thread.
185+
- **[`total_steal_operations`]**
186+
The number of times worker threads stole tasks from another worker thread.
187+
- **[`max_steal_operations`]**
188+
The maximum number of times any worker thread stole tasks from another worker thread.
189+
- **[`min_steal_operations`]**
190+
The minimum number of times any worker thread stole tasks from another worker thread.
185191
- **[`num_remote_schedules`]**
186192
The number of tasks scheduled from outside of the runtime.
187193
- **[`total_local_schedule_count`]**
@@ -233,6 +239,9 @@ tokio::spawn(do_work());
233239
[`total_steal_count`]: https://docs.rs/tokio-metrics/0.1.*/tokio_metrics/struct.RuntimeMetrics.html#structfield.total_steal_count
234240
[`max_steal_count`]: https://docs.rs/tokio-metrics/0.1.*/tokio_metrics/struct.RuntimeMetrics.html#structfield.max_steal_count
235241
[`min_steal_count`]: https://docs.rs/tokio-metrics/0.1.*/tokio_metrics/struct.RuntimeMetrics.html#structfield.min_steal_count
242+
[`total_steal_operations`]: https://docs.rs/tokio-metrics/0.1.*/tokio_metrics/struct.RuntimeMetrics.html#structfield.total_steal_operations
243+
[`max_steal_operations`]: https://docs.rs/tokio-metrics/0.1.*/tokio_metrics/struct.RuntimeMetrics.html#structfield.max_steal_operations
244+
[`min_steal_operations`]: https://docs.rs/tokio-metrics/0.1.*/tokio_metrics/struct.RuntimeMetrics.html#structfield.min_steal_operations
236245
[`num_remote_schedules`]: https://docs.rs/tokio-metrics/0.1.*/tokio_metrics/struct.RuntimeMetrics.html#structfield.num_remote_schedules
237246
[`total_local_schedule_count`]: https://docs.rs/tokio-metrics/0.1.*/tokio_metrics/struct.RuntimeMetrics.html#structfield.total_local_schedule_count
238247
[`max_local_schedule_count`]: https://docs.rs/tokio-metrics/0.1.*/tokio_metrics/struct.RuntimeMetrics.html#structfield.max_local_schedule_count

src/runtime.rs

Lines changed: 98 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ pub struct RuntimeMetrics {
256256

257257
/// The number of tasks worker threads stole from another worker thread.
258258
///
259-
/// The worker steal count starts increases by the amount of stolen tasks each time the worker
259+
/// The worker steal count increases by the amount of stolen tasks each time the worker
260260
/// has processed its scheduled queue and successfully steals more pending tasks from another
261261
/// worker.
262262
///
@@ -344,6 +344,95 @@ pub struct RuntimeMetrics {
344344
/// - [`RuntimeMetrics::max_steal_count`]
345345
pub min_steal_count: u64,
346346

347+
/// The number of times worker threads stole tasks from another worker thread.
348+
///
349+
/// The worker steal operations increases by one each time the worker has processed its
350+
/// scheduled queue and successfully steals more pending tasks from another worker.
351+
///
352+
/// This metric only applies to the **multi-threaded** runtime and will always return `0` when
353+
/// using the current thread runtime.
354+
///
355+
/// ##### Definition
356+
/// This metric is derived from the sum of [`tokio::runtime::RuntimeMetrics::worker_steal_operations`]
357+
/// for all worker threads.
358+
///
359+
/// ##### See also
360+
/// - [`RuntimeMetrics::min_steal_operations`]
361+
/// - [`RuntimeMetrics::max_steal_operations`]
362+
///
363+
/// ##### Examples
364+
/// In the below example, a blocking channel is used to backup one worker thread:
365+
/// ```
366+
/// #[tokio::main(flavor = "multi_thread", worker_threads = 2)]
367+
/// async fn main() {
368+
/// let handle = tokio::runtime::Handle::current();
369+
/// let monitor = tokio_metrics::RuntimeMonitor::new(&handle);
370+
/// let mut intervals = monitor.intervals();
371+
/// let mut next_interval = || intervals.next().unwrap();
372+
///
373+
/// let interval = next_interval(); // end of first sampling interval
374+
/// assert_eq!(interval.total_steal_operations, 0);
375+
/// assert_eq!(interval.min_steal_operations, 0);
376+
/// assert_eq!(interval.max_steal_operations, 0);
377+
///
378+
/// // induce a steal
379+
/// async {
380+
/// let (tx, rx) = std::sync::mpsc::channel();
381+
/// // Move to the runtime.
382+
/// tokio::spawn(async move {
383+
/// // Spawn the task that sends to the channel
384+
/// tokio::spawn(async move {
385+
/// tx.send(()).unwrap();
386+
/// });
387+
/// // Spawn a task that bumps the previous task out of the "next
388+
/// // scheduled" slot.
389+
/// tokio::spawn(async {});
390+
/// // Blocking receive on the channe.
391+
/// rx.recv().unwrap();
392+
/// flush_metrics().await;
393+
/// }).await.unwrap();
394+
/// flush_metrics().await;
395+
/// }.await;
396+
///
397+
/// let interval = { flush_metrics().await; next_interval() }; // end of interval 2
398+
/// assert_eq!(interval.total_steal_operations, 1);
399+
/// assert_eq!(interval.min_steal_operations, 0);
400+
/// assert_eq!(interval.max_steal_operations, 1);
401+
///
402+
/// let interval = { flush_metrics().await; next_interval() }; // end of interval 3
403+
/// assert_eq!(interval.total_steal_operations, 0);
404+
/// assert_eq!(interval.min_steal_operations, 0);
405+
/// assert_eq!(interval.max_steal_operations, 0);
406+
/// }
407+
///
408+
/// async fn flush_metrics() {
409+
/// let _ = tokio::time::sleep(std::time::Duration::ZERO).await;
410+
/// }
411+
/// ```
412+
pub total_steal_operations: u64,
413+
414+
/// The maximum number of times any worker thread stole tasks from another worker thread.
415+
///
416+
/// ##### Definition
417+
/// This metric is derived from the maximum of [`tokio::runtime::RuntimeMetrics::worker_steal_operations`]
418+
/// across all worker threads.
419+
///
420+
/// ##### See also
421+
/// - [`RuntimeMetrics::total_steal_operations`]
422+
/// - [`RuntimeMetrics::min_steal_operations`]
423+
pub max_steal_operations: u64,
424+
425+
/// The minimum number of times any worker thread stole tasks from another worker thread.
426+
///
427+
/// ##### Definition
428+
/// This metric is derived from the minimum of [`tokio::runtime::RuntimeMetrics::worker_steal_operations`]
429+
/// across all worker threads.
430+
///
431+
/// ##### See also
432+
/// - [`RuntimeMetrics::total_steal_operations`]
433+
/// - [`RuntimeMetrics::max_steal_operations`]
434+
pub min_steal_operations: u64,
435+
347436
/// The number of tasks scheduled from **outside** of the runtime.
348437
///
349438
/// The remote schedule count increases by one each time a task is woken from **outside** of
@@ -959,6 +1048,7 @@ struct Worker {
9591048
total_park_count: u64,
9601049
total_noop_count: u64,
9611050
total_steal_count: u64,
1051+
total_steal_operations: u64,
9621052
total_local_schedule_count: u64,
9631053
total_overflow_count: u64,
9641054
total_polls_count: u64,
@@ -1106,6 +1196,7 @@ impl Worker {
11061196
total_park_count: rt.worker_park_count(worker),
11071197
total_noop_count: rt.worker_noop_count(worker),
11081198
total_steal_count: rt.worker_steal_count(worker),
1199+
total_steal_operations: rt.worker_steal_operations(worker),
11091200
total_local_schedule_count: rt.worker_local_schedule_count(worker),
11101201
total_overflow_count: rt.worker_overflow_count(worker),
11111202
total_polls_count: rt.worker_poll_count(worker),
@@ -1150,6 +1241,12 @@ impl Worker {
11501241
min_steal_count,
11511242
worker_steal_count
11521243
);
1244+
metric!(
1245+
total_steal_operations,
1246+
max_steal_operations,
1247+
min_steal_operations,
1248+
worker_steal_operations
1249+
);
11531250
metric!(
11541251
total_local_schedule_count,
11551252
max_local_schedule_count,

0 commit comments

Comments
 (0)