scx_flash/
stats.rs

1// SPDX-License-Identifier: GPL-2.0
2//
3// Copyright (c) 2024 Andrea Righi <arighi@nvidia.com>
4
5// This software may be used and distributed according to the terms of the
6// GNU General Public License version 2.
7
8use std::io::Write;
9use std::sync::atomic::AtomicBool;
10use std::sync::atomic::Ordering;
11use std::sync::Arc;
12use std::time::Duration;
13
14use anyhow::Result;
15use scx_stats::prelude::*;
16use scx_stats_derive::Stats;
17use serde::Deserialize;
18use serde::Serialize;
19
20#[derive(Clone, Debug, Default, Serialize, Deserialize, Stats)]
21#[stat(top)]
22pub struct Metrics {
23    #[stat(desc = "Number of kthread direct dispatches")]
24    pub nr_kthread_dispatches: u64,
25    #[stat(desc = "Number of task direct dispatches")]
26    pub nr_direct_dispatches: u64,
27    #[stat(desc = "Number of task global dispatches")]
28    pub nr_shared_dispatches: u64,
29}
30
31impl Metrics {
32    fn format<W: Write>(&self, w: &mut W) -> Result<()> {
33        writeln!(
34            w,
35            "[{}] dispatch -> kthread: {:<5} direct: {:<5} shared: {:<5}",
36            crate::SCHEDULER_NAME,
37            self.nr_kthread_dispatches,
38            self.nr_direct_dispatches,
39            self.nr_shared_dispatches,
40        )?;
41        Ok(())
42    }
43
44    fn delta(&self, rhs: &Self) -> Self {
45        Self {
46            nr_kthread_dispatches: self.nr_kthread_dispatches - rhs.nr_kthread_dispatches,
47            nr_direct_dispatches: self.nr_direct_dispatches - rhs.nr_direct_dispatches,
48            nr_shared_dispatches: self.nr_shared_dispatches - rhs.nr_shared_dispatches,
49            ..self.clone()
50        }
51    }
52}
53
54pub fn server_data() -> StatsServerData<(), Metrics> {
55    let open: Box<dyn StatsOpener<(), Metrics>> = Box::new(move |(req_ch, res_ch)| {
56        req_ch.send(())?;
57        let mut prev = res_ch.recv()?;
58
59        let read: Box<dyn StatsReader<(), Metrics>> = Box::new(move |_args, (req_ch, res_ch)| {
60            req_ch.send(())?;
61            let cur = res_ch.recv()?;
62            let delta = cur.delta(&prev);
63            prev = cur;
64            delta.to_json()
65        });
66
67        Ok(read)
68    });
69
70    StatsServerData::new()
71        .add_meta(Metrics::meta())
72        .add_ops("top", StatsOps { open, close: None })
73}
74
75pub fn monitor(intv: Duration, shutdown: Arc<AtomicBool>) -> Result<()> {
76    scx_utils::monitor_stats::<Metrics>(
77        &vec![],
78        intv,
79        || shutdown.load(Ordering::Relaxed),
80        |metrics| metrics.format(&mut std::io::stdout()),
81    )
82}