mirror of
https://github.com/sched-ext/scx.git
synced 2024-11-24 20:00:22 +00:00
Merge pull request #763 from ryantimwilson/rusty-default-weights-fix
[rusty] Fix load stats when host is under-utilized
This commit is contained in:
commit
2b5829e275
@ -83,4 +83,5 @@ pub use log_recorder::LogRecorderBuilder;
|
|||||||
|
|
||||||
mod misc;
|
mod misc;
|
||||||
pub use misc::monitor_stats;
|
pub use misc::monitor_stats;
|
||||||
|
pub use misc::normalize_load_metric;
|
||||||
pub use misc::set_rlimit_infinity;
|
pub use misc::set_rlimit_infinity;
|
||||||
|
@ -90,3 +90,25 @@ pub fn read_file_usize(path: &Path) -> Result<usize> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Load is reported as weight * duty cycle
|
||||||
|
*
|
||||||
|
* In the Linux kernel, EEDVF uses default weight = 1 s.t.
|
||||||
|
* load for a nice-0 thread runnable for time slice = 1
|
||||||
|
*
|
||||||
|
* To conform with cgroup weights convention, sched-ext uses
|
||||||
|
* the convention of default weight = 100 with the formula
|
||||||
|
* 100 * nice ^ 1.5. This means load for a nice-0 thread
|
||||||
|
* runnable for time slice = 100.
|
||||||
|
*
|
||||||
|
* To ensure we report load metrics consistently with the Linux
|
||||||
|
* kernel, we divide load by 100.0 prior to reporting metrics.
|
||||||
|
* This is also more intuitive for users since 1 CPU roughly
|
||||||
|
* means 1 unit of load.
|
||||||
|
*
|
||||||
|
* We only do this prior to reporting as its easier to work with
|
||||||
|
* weight as integers in BPF / userspace than floating point.
|
||||||
|
*/
|
||||||
|
pub fn normalize_load_metric(metric: f64) -> f64 {
|
||||||
|
metric / 100.0
|
||||||
|
}
|
||||||
|
@ -18,6 +18,7 @@ use log::warn;
|
|||||||
use scx_stats::prelude::*;
|
use scx_stats::prelude::*;
|
||||||
use scx_stats_derive::stat_doc;
|
use scx_stats_derive::stat_doc;
|
||||||
use scx_stats_derive::Stats;
|
use scx_stats_derive::Stats;
|
||||||
|
use scx_utils::normalize_load_metric;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
@ -182,7 +183,7 @@ impl LayerStats {
|
|||||||
Self {
|
Self {
|
||||||
util: stats.layer_utils[lidx] * 100.0,
|
util: stats.layer_utils[lidx] * 100.0,
|
||||||
util_frac: calc_frac(stats.layer_utils[lidx], stats.total_util),
|
util_frac: calc_frac(stats.layer_utils[lidx], stats.total_util),
|
||||||
load: stats.layer_loads[lidx],
|
load: normalize_load_metric(stats.layer_loads[lidx]),
|
||||||
load_adj: calc_frac(stats.layer_load_sums[lidx], stats.total_load_sum),
|
load_adj: calc_frac(stats.layer_load_sums[lidx], stats.total_load_sum),
|
||||||
dcycle: calc_frac(stats.layer_dcycle_sums[lidx], stats.total_dcycle_sum),
|
dcycle: calc_frac(stats.layer_dcycle_sums[lidx], stats.total_dcycle_sum),
|
||||||
load_frac: calc_frac(stats.layer_loads[lidx], stats.total_load),
|
load_frac: calc_frac(stats.layer_loads[lidx], stats.total_load),
|
||||||
@ -411,7 +412,7 @@ impl SysStats {
|
|||||||
proc_ms: stats.processing_dur.as_millis() as u64,
|
proc_ms: stats.processing_dur.as_millis() as u64,
|
||||||
busy: stats.cpu_busy * 100.0,
|
busy: stats.cpu_busy * 100.0,
|
||||||
util: stats.total_util * 100.0,
|
util: stats.total_util * 100.0,
|
||||||
load: stats.total_load,
|
load: normalize_load_metric(stats.total_load),
|
||||||
fallback_cpu: fallback_cpu as u32,
|
fallback_cpu: fallback_cpu as u32,
|
||||||
layers: BTreeMap::new(),
|
layers: BTreeMap::new(),
|
||||||
})
|
})
|
||||||
|
@ -155,6 +155,7 @@ use crate::stats::DomainStats;
|
|||||||
use crate::stats::NodeStats;
|
use crate::stats::NodeStats;
|
||||||
use crate::DomainGroup;
|
use crate::DomainGroup;
|
||||||
|
|
||||||
|
const DEFAULT_WEIGHT: f64 = bpf_intf::consts_LB_DEFAULT_WEIGHT as f64;
|
||||||
const RAVG_FRAC_BITS: u32 = bpf_intf::ravg_consts_RAVG_FRAC_BITS;
|
const RAVG_FRAC_BITS: u32 = bpf_intf::ravg_consts_RAVG_FRAC_BITS;
|
||||||
|
|
||||||
fn now_monotonic() -> u64 {
|
fn now_monotonic() -> u64 {
|
||||||
@ -446,20 +447,16 @@ impl NumaNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn stats(&self) -> NodeStats {
|
fn stats(&self) -> NodeStats {
|
||||||
let mut stats = NodeStats {
|
let mut stats = NodeStats::new(
|
||||||
load: self.load.load_sum(),
|
self.load.load_sum(),
|
||||||
imbal: self.load.imbal(),
|
self.load.imbal(),
|
||||||
delta: self.load.delta(),
|
self.load.delta(),
|
||||||
doms: BTreeMap::new(),
|
BTreeMap::new(),
|
||||||
};
|
);
|
||||||
for dom in self.domains.iter() {
|
for dom in self.domains.iter() {
|
||||||
stats.doms.insert(
|
stats.doms.insert(
|
||||||
dom.id,
|
dom.id,
|
||||||
DomainStats {
|
DomainStats::new(dom.load.load_sum(), dom.load.imbal(), dom.load.delta()),
|
||||||
load: dom.load.load_sum(),
|
|
||||||
imbal: dom.load.imbal(),
|
|
||||||
delta: dom.load.delta(),
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
stats
|
stats
|
||||||
@ -542,8 +539,13 @@ impl<'a, 'b> LoadBalancer<'a, 'b> {
|
|||||||
|
|
||||||
let (dom_loads, total_load) = if !self.lb_apply_weight {
|
let (dom_loads, total_load) = if !self.lb_apply_weight {
|
||||||
(
|
(
|
||||||
ledger.dom_dcycle_sums().to_vec(),
|
ledger
|
||||||
ledger.global_dcycle_sum(),
|
.dom_dcycle_sums()
|
||||||
|
.to_vec()
|
||||||
|
.into_iter()
|
||||||
|
.map(|d| DEFAULT_WEIGHT * d)
|
||||||
|
.collect(),
|
||||||
|
DEFAULT_WEIGHT * ledger.global_dcycle_sum(),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
self.infeas_threshold = ledger.effective_max_weight();
|
self.infeas_threshold = ledger.effective_max_weight();
|
||||||
@ -696,10 +698,12 @@ impl<'a, 'b> LoadBalancer<'a, 'b> {
|
|||||||
RAVG_FRAC_BITS,
|
RAVG_FRAC_BITS,
|
||||||
);
|
);
|
||||||
|
|
||||||
if self.lb_apply_weight {
|
let weight = if self.lb_apply_weight {
|
||||||
let weight = (task_ctx.weight as f64).min(self.infeas_threshold);
|
(task_ctx.weight as f64).min(self.infeas_threshold)
|
||||||
|
} else {
|
||||||
|
DEFAULT_WEIGHT
|
||||||
|
};
|
||||||
load *= weight;
|
load *= weight;
|
||||||
}
|
|
||||||
|
|
||||||
dom.tasks.insert(TaskInfo {
|
dom.tasks.insert(TaskInfo {
|
||||||
tptr,
|
tptr,
|
||||||
|
@ -12,6 +12,7 @@ use chrono::Local;
|
|||||||
use scx_stats::prelude::*;
|
use scx_stats::prelude::*;
|
||||||
use scx_stats_derive::stat_doc;
|
use scx_stats_derive::stat_doc;
|
||||||
use scx_stats_derive::Stats;
|
use scx_stats_derive::Stats;
|
||||||
|
use scx_utils::normalize_load_metric;
|
||||||
use scx_utils::Cpumask;
|
use scx_utils::Cpumask;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
@ -39,6 +40,14 @@ pub struct DomainStats {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl DomainStats {
|
impl DomainStats {
|
||||||
|
pub fn new(load: f64, imbal: f64, delta: f64) -> Self {
|
||||||
|
Self {
|
||||||
|
load: normalize_load_metric(load),
|
||||||
|
imbal: normalize_load_metric(imbal),
|
||||||
|
delta: normalize_load_metric(delta),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn format<W: Write>(&self, w: &mut W, id: usize) -> Result<()> {
|
pub fn format<W: Write>(&self, w: &mut W, id: usize) -> Result<()> {
|
||||||
writeln!(
|
writeln!(
|
||||||
w,
|
w,
|
||||||
@ -67,6 +76,15 @@ pub struct NodeStats {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl NodeStats {
|
impl NodeStats {
|
||||||
|
pub fn new(load: f64, imbal: f64, delta: f64, doms: BTreeMap<usize, DomainStats>) -> Self {
|
||||||
|
Self {
|
||||||
|
load: normalize_load_metric(load),
|
||||||
|
imbal: normalize_load_metric(imbal),
|
||||||
|
delta: normalize_load_metric(delta),
|
||||||
|
doms,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn format<W: Write>(&self, w: &mut W, id: usize) -> Result<()> {
|
pub fn format<W: Write>(&self, w: &mut W, id: usize) -> Result<()> {
|
||||||
writeln!(
|
writeln!(
|
||||||
w,
|
w,
|
||||||
|
Loading…
Reference in New Issue
Block a user