mirror of
https://github.com/JakeHillion/scx.git
synced 2024-11-26 03:20:24 +00:00
scx_lavd: print basic system status when --monior is given
Signed-off-by: Changwoo Min <changwoo@igalia.com>
This commit is contained in:
parent
6b717a3f3d
commit
e5d27d0553
@ -197,8 +197,8 @@ char _license[] SEC("license") = "GPL";
|
||||
volatile u64 nr_cpus_onln;
|
||||
static volatile u64 nr_cpus_big;
|
||||
|
||||
static struct sys_stat __sys_stats[2];
|
||||
static volatile int __sys_stat_idx;
|
||||
struct sys_stat __sys_stats[2];
|
||||
volatile int __sys_stat_idx;
|
||||
|
||||
private(LAVD) struct bpf_cpumask __kptr *turbo_cpumask; /* CPU mask for turbo CPUs */
|
||||
private(LAVD) struct bpf_cpumask __kptr *big_cpumask; /* CPU mask for big CPUs */
|
||||
|
@ -12,6 +12,7 @@ pub mod bpf_intf;
|
||||
pub use bpf_intf::*;
|
||||
|
||||
mod stats;
|
||||
use stats::SysStats;
|
||||
use stats::SchedSample;
|
||||
use stats::SchedSamples;
|
||||
use stats::StatsReq;
|
||||
@ -122,6 +123,14 @@ struct Opts {
|
||||
#[clap(long = "no-freq-scaling", action = clap::ArgAction::SetTrue)]
|
||||
no_freq_scaling: bool,
|
||||
|
||||
/// Enable stats monitoring with the specified interval.
|
||||
#[clap(long)]
|
||||
stats: Option<f64>,
|
||||
|
||||
/// Run in stats monitoring mode with the specified interval. Scheduler is not launched.
|
||||
#[clap(long)]
|
||||
monitor: Option<f64>,
|
||||
|
||||
/// Run in monitoring mode. Show the specified number of scheduling
|
||||
/// samples every second.
|
||||
#[clap(long)]
|
||||
@ -452,8 +461,9 @@ struct Scheduler<'a> {
|
||||
rb_mgr: libbpf_rs::RingBuffer<'static>,
|
||||
intrspc: introspec,
|
||||
intrspc_rx: Receiver<SchedSample>,
|
||||
sampler_tid: Option<ThreadId>,
|
||||
monitor_tid: Option<ThreadId>,
|
||||
stats_server: StatsServer<StatsReq, StatsRes>,
|
||||
mseq_id: u64,
|
||||
}
|
||||
|
||||
impl<'a> Scheduler<'a> {
|
||||
@ -498,8 +508,9 @@ impl<'a> Scheduler<'a> {
|
||||
rb_mgr,
|
||||
intrspc: introspec::new(),
|
||||
intrspc_rx,
|
||||
sampler_tid: None,
|
||||
monitor_tid: None,
|
||||
stats_server,
|
||||
mseq_id: 0,
|
||||
})
|
||||
}
|
||||
|
||||
@ -634,15 +645,35 @@ impl<'a> Scheduler<'a> {
|
||||
Ok(match req {
|
||||
StatsReq::NewSampler(tid) => {
|
||||
self.rb_mgr.consume().unwrap();
|
||||
self.sampler_tid = Some(*tid);
|
||||
self.monitor_tid = Some(*tid);
|
||||
StatsRes::Ack
|
||||
}
|
||||
StatsReq::SysStatsReq {
|
||||
tid,
|
||||
} => {
|
||||
if Some(*tid) != self.monitor_tid {
|
||||
return Ok(StatsRes::Bye);
|
||||
}
|
||||
self.mseq_id += 1;
|
||||
|
||||
let mseq = self.mseq_id;
|
||||
let avg_svc_time = self.skel.maps.bss_data.__sys_stats[0].avg_svc_time;
|
||||
let nr_queued_task = self.skel.maps.bss_data.__sys_stats[0].nr_queued_task;
|
||||
let nr_active = self.skel.maps.bss_data.__sys_stats[0].nr_active;
|
||||
|
||||
StatsRes::SysStats(SysStats {
|
||||
mseq,
|
||||
avg_svc_time,
|
||||
nr_queued_task,
|
||||
nr_active,
|
||||
})
|
||||
}
|
||||
StatsReq::SchedSamplesNr {
|
||||
tid,
|
||||
nr_samples,
|
||||
interval_ms,
|
||||
} => {
|
||||
if Some(*tid) != self.sampler_tid {
|
||||
if Some(*tid) != self.monitor_tid {
|
||||
return Ok(StatsRes::Bye);
|
||||
}
|
||||
|
||||
@ -817,6 +848,17 @@ fn main() -> Result<()> {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if let Some(intv) = opts.monitor.or(opts.stats) {
|
||||
let shutdown_copy = shutdown.clone();
|
||||
let jh = std::thread::spawn(move || {
|
||||
stats::monitor(Duration::from_secs_f64(intv), shutdown_copy).unwrap()
|
||||
});
|
||||
if opts.monitor.is_some() {
|
||||
let _ = jh.join();
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
let mut open_object = MaybeUninit::uninit();
|
||||
loop {
|
||||
let mut sched = Scheduler::init(&opts, &mut open_object)?;
|
||||
|
@ -12,10 +12,56 @@ use std::sync::Arc;
|
||||
use std::thread::ThreadId;
|
||||
use std::time::Duration;
|
||||
|
||||
#[derive(Clone, Debug, Default, Serialize, Deserialize, Stats)]
|
||||
pub struct SysStats {
|
||||
#[stat(desc = "Sequence ID of this messge")]
|
||||
pub mseq: u64,
|
||||
|
||||
#[stat(desc = "Average runtime per schedule")]
|
||||
pub avg_svc_time: u64,
|
||||
|
||||
#[stat(desc = "Number of runnable tasks in runqueues")]
|
||||
pub nr_queued_task: u64,
|
||||
|
||||
#[stat(desc = "Number of active CPUs when core compaction is enabled")]
|
||||
pub nr_active: u32,
|
||||
}
|
||||
|
||||
impl SysStats {
|
||||
pub fn format_header<W: Write>(w: &mut W) -> Result<()> {
|
||||
writeln!(
|
||||
w,
|
||||
"| {} | {} | {} | {} |",
|
||||
"mseq",
|
||||
"avg_svc_time",
|
||||
"nr_queued_task",
|
||||
"nr_active",
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn format<W: Write>(&self, w: &mut W) -> Result<()> {
|
||||
if self.mseq % 32 == 1 {
|
||||
Self::format_header(w)?;
|
||||
}
|
||||
|
||||
writeln!(
|
||||
w,
|
||||
"| {} | {} | {} | {} |",
|
||||
self.mseq,
|
||||
self.avg_svc_time,
|
||||
self.nr_queued_task,
|
||||
self.nr_active,
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, Serialize, Deserialize, Stats)]
|
||||
#[stat(top)]
|
||||
pub struct SchedSample {
|
||||
#[stat(desc = "Sequence ID of task log")]
|
||||
#[stat(desc = "Sequence ID of this message")]
|
||||
pub mseq: u64,
|
||||
#[stat(desc = "Process ID")]
|
||||
pub pid: i32,
|
||||
@ -149,6 +195,9 @@ pub struct SchedSamples {
|
||||
#[derive(Debug)]
|
||||
pub enum StatsReq {
|
||||
NewSampler(ThreadId),
|
||||
SysStatsReq {
|
||||
tid: ThreadId,
|
||||
},
|
||||
SchedSamplesNr {
|
||||
tid: ThreadId,
|
||||
nr_samples: u64,
|
||||
@ -157,7 +206,15 @@ pub enum StatsReq {
|
||||
}
|
||||
|
||||
impl StatsReq {
|
||||
fn from_args(
|
||||
fn from_args_stats(
|
||||
tid: ThreadId,
|
||||
) -> Result<Self> {
|
||||
Ok(Self::SysStatsReq {
|
||||
tid,
|
||||
})
|
||||
}
|
||||
|
||||
fn from_args_samples(
|
||||
tid: ThreadId,
|
||||
nr_cpus_onln: u64,
|
||||
args: &BTreeMap<String, String>,
|
||||
@ -187,12 +244,12 @@ impl StatsReq {
|
||||
pub enum StatsRes {
|
||||
Ack,
|
||||
Bye,
|
||||
SysStats(SysStats),
|
||||
SchedSamples(SchedSamples),
|
||||
}
|
||||
|
||||
pub fn server_data(nr_cpus_onln: u64) -> StatsServerData<StatsReq, StatsRes> {
|
||||
let samples_open: Box<dyn StatsOpener<StatsReq, StatsRes>> =
|
||||
Box::new(move |(req_ch, res_ch)| {
|
||||
let open: Box<dyn StatsOpener<StatsReq, StatsRes>> = Box::new(move |(req_ch, res_ch)| {
|
||||
let tid = std::thread::current().id();
|
||||
req_ch.send(StatsReq::NewSampler(tid))?;
|
||||
match res_ch.recv()? {
|
||||
@ -202,7 +259,31 @@ pub fn server_data(nr_cpus_onln: u64) -> StatsServerData<StatsReq, StatsRes> {
|
||||
|
||||
let read: Box<dyn StatsReader<StatsReq, StatsRes>> =
|
||||
Box::new(move |args, (req_ch, res_ch)| {
|
||||
let req = StatsReq::from_args(tid, nr_cpus_onln, args)?;
|
||||
let req = StatsReq::from_args_stats(tid)?;
|
||||
req_ch.send(req)?;
|
||||
|
||||
let stats = match res_ch.recv()? {
|
||||
StatsRes::SysStats(v) => v,
|
||||
StatsRes::Bye => bail!("preempted by another sampler"),
|
||||
res => bail!("invalid response: {:?}", &res),
|
||||
};
|
||||
|
||||
stats.to_json()
|
||||
});
|
||||
Ok(read)
|
||||
});
|
||||
|
||||
let samples_open: Box<dyn StatsOpener<StatsReq, StatsRes>> = Box::new(move |(req_ch, res_ch)| {
|
||||
let tid = std::thread::current().id();
|
||||
req_ch.send(StatsReq::NewSampler(tid))?;
|
||||
match res_ch.recv()? {
|
||||
StatsRes::Ack => {}
|
||||
res => bail!("invalid response: {:?}", &res),
|
||||
}
|
||||
|
||||
let read: Box<dyn StatsReader<StatsReq, StatsRes>> =
|
||||
Box::new(move |args, (req_ch, res_ch)| {
|
||||
let req = StatsReq::from_args_samples(tid, nr_cpus_onln, args)?;
|
||||
req_ch.send(req)?;
|
||||
|
||||
let samples = match res_ch.recv()? {
|
||||
@ -217,6 +298,14 @@ pub fn server_data(nr_cpus_onln: u64) -> StatsServerData<StatsReq, StatsRes> {
|
||||
});
|
||||
|
||||
StatsServerData::new()
|
||||
.add_meta(SysStats::meta())
|
||||
.add_ops(
|
||||
"top",
|
||||
StatsOps {
|
||||
open: open,
|
||||
close: None,
|
||||
},
|
||||
)
|
||||
.add_meta(SchedSample::meta())
|
||||
.add_ops(
|
||||
"sched_samples",
|
||||
@ -244,3 +333,13 @@ pub fn monitor_sched_samples(nr_samples: u64, shutdown: Arc<AtomicBool>) -> Resu
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub fn monitor(intv: Duration, shutdown: Arc<AtomicBool>) -> Result<()> {
|
||||
scx_utils::monitor_stats::<SysStats>(
|
||||
&vec![],
|
||||
intv,
|
||||
|| shutdown.load(Ordering::Relaxed),
|
||||
|sysstats| sysstats.format(&mut std::io::stdout()),
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user