scx_layered: Add stats for XNUMA/XLLC migrations

Add stats for XNUMA/XLLC migrations. An example of the output is shown:
```
  hodgesd  : util/frac=    5.4/  0.1 load/frac=    301.0/  0.3 tasks=   476
             tot=   3168 local=97.82 wake/exp/reenq= 2.18/ 0.00/ 0.00
             keep/max/busy= 0.03/ 0.00/ 0.03 kick= 0.00 yield/ign= 0.09/    0
             open_idle= 0.00 mig= 6.82 xnuma_mig= 6.82 xllc_mig= 4.86 affn_viol= 0.00
             preempt/first/idle/fail= 0.00/ 0.00/ 0.00/ 0.00 min_exec= 0.00/   0.00ms
             cpus=  2 [  2,  4] 00000000 00000010 00001000
  normal   : util/frac=   28.7/  0.7 load/frac= 101704.7/ 95.8 tasks=  2450
             tot=   4660 local=99.06 wake/exp/reenq= 0.88/ 0.06/ 0.00
             keep/max/busy= 1.03/ 0.00/ 0.00 kick= 0.06 yield/ign= 0.04/  400
             open_idle=15.73 mig=23.45 xnuma_mig=23.45 xllc_mig= 3.07 affn_viol= 0.00
             preempt/first/idle/fail= 0.00/ 0.00/ 0.00/ 0.88 min_exec= 0.00/   0.00ms
             cpus=  2 [  2,  2] 00000001 00000100 00000000
             excl_coll=12.55 excl_preempt= 0.00
  random   : util/frac=    0.0/  0.0 load/frac=      0.0/  0.0 tasks=     0
             tot=      0 local= 0.00 wake/exp/reenq= 0.00/ 0.00/ 0.00
             keep/max/busy= 0.00/ 0.00/ 0.00 kick= 0.00 yield/ign= 0.00/    0
             open_idle= 0.00 mig= 0.00 xnuma_mig= 0.00 xllc_mig= 0.00 affn_viol= 0.00
             preempt/first/idle/fail= 0.00/ 0.00/ 0.00/ 0.00 min_exec= 0.00/   0.00ms
             cpus=  0 [  0,  0] 00000000 00000000 00000000
             excl_coll= 0.00 excl_preempt= 0.00
  stress-ng: util/frac= 4189.1/ 99.2 load/frac=   4200.0/  4.0 tasks=    43
             tot=     62 local= 0.00 wake/exp/reenq= 0.00/100.0/ 0.00
             keep/max/busy=2433.9/177.4/ 0.00 kick=100.0 yield/ign= 3.23/    0
             open_idle= 0.00 mig=54.84 xnuma_mig=54.84 xllc_mig=35.48 affn_viol= 0.00
             preempt/first/idle/fail= 0.00/ 0.00/ 0.00/ 0.00 min_exec= 0.00/   0.00ms
             cpus=  4 [  4,  4] 00000300 00030000 00000000
             excl_coll= 0.00 excl_preempt= 0.00
```

Signed-off-by: Daniel Hodges <hodges.daniel.scott@gmail.com>
This commit is contained in:
Daniel Hodges 2024-09-10 19:37:21 -07:00
parent 85863d0e1c
commit 43ec8bfe82
3 changed files with 108 additions and 6 deletions

View File

@ -71,6 +71,8 @@ enum layer_stat_idx {
LSTAT_YIELD,
LSTAT_YIELD_IGNORE,
LSTAT_MIGRATION,
LSTAT_XNUMA_MIGRATION,
LSTAT_XLLC_MIGRATION,
NR_LSTATS,
};
@ -86,6 +88,8 @@ struct cpu_ctx {
u64 lstats[MAX_LAYERS][NR_LSTATS];
u64 ran_current_for;
u32 layer_idx;
u32 node_idx;
u32 cache_idx;
};
struct cache_ctx {

View File

@ -136,9 +136,6 @@ static u32 cpu_to_llc_id(s32 cpu_id)
return *llc_ptr;
}
/*
* Numa node context
*/
struct {
__uint(type, BPF_MAP_TYPE_ARRAY);
__type(key, u32);
@ -147,6 +144,30 @@ struct {
__uint(map_flags, 0);
} node_data SEC(".maps");
static struct node_ctx *lookup_node_ctx(u32 node)
{
struct node_ctx *nodec;
nodec = bpf_map_lookup_elem(&node_data, &node);
return nodec;
}
struct {
__uint(type, BPF_MAP_TYPE_ARRAY);
__type(key, u32);
__type(value, struct cache_ctx);
__uint(max_entries, MAX_DOMS);
__uint(map_flags, 0);
} cache_data SEC(".maps");
static struct cache_ctx *lookup_cache_ctx(u32 cache_idx)
{
struct cache_ctx *cachec;
cachec = bpf_map_lookup_elem(&cache_data, &cache_idx);
return cachec;
}
static void gstat_inc(enum global_stat_idx idx, struct cpu_ctx *cctx)
{
if (idx < 0 || idx >= NR_GSTATS) {
@ -1166,6 +1187,7 @@ static s32 create_node(u32 node_id)
u32 cpu;
struct bpf_cpumask *cpumask;
struct node_ctx *nodec;
struct cpu_ctx *cctx;
s32 ret;
nodec = bpf_map_lookup_elem(&node_data, &node_id);
@ -1198,8 +1220,58 @@ static s32 create_node(u32 node_id)
break;
}
if (*nmask & (1LLU << (cpu % 64)))
if (*nmask & (1LLU << (cpu % 64))) {
bpf_cpumask_set_cpu(cpu, cpumask);
if (!(cctx = lookup_cpu_ctx(-1))) {
scx_bpf_error("cpu ctx error");
ret = -ENOENT;
break;
}
cctx->node_idx = node_id;
}
}
bpf_rcu_read_unlock();
return ret;
}
static s32 create_cache(u32 cache_id)
{
u32 cpu, llc_id;
struct bpf_cpumask *cpumask;
struct cache_ctx *cachec;
struct cpu_ctx *cctx;
s32 ret;
cachec = bpf_map_lookup_elem(&cache_data, &cache_id);
if (!cachec) {
scx_bpf_error("No cache%u", cache_id);
return -ENOENT;
}
cachec->id = cache_id;
ret = create_save_cpumask(&cachec->cpumask);
if (ret)
return ret;
bpf_rcu_read_lock();
cpumask = cachec->cpumask;
if (!cpumask) {
bpf_rcu_read_unlock();
scx_bpf_error("Failed to lookup node cpumask");
return -ENOENT;
}
bpf_for(cpu, 0, MAX_CPUS) {
llc_id = cpu_to_llc_id(cpu);
if (llc_id != cache_id)
continue;
bpf_cpumask_set_cpu(cpu, cpumask);
if (!(cctx = lookup_cpu_ctx(-1))) {
scx_bpf_error("cpu ctx error"); ret = -ENOENT; break;
}
cctx->cache_idx = cache_id;
}
bpf_rcu_read_unlock();
@ -1225,14 +1297,27 @@ void BPF_STRUCT_OPS(layered_running, struct task_struct *p)
struct cpu_ctx *cctx;
struct task_ctx *tctx;
struct layer *layer;
struct node_ctx *nodec;
struct cache_ctx *cachec;
s32 task_cpu = scx_bpf_task_cpu(p);
if (!(cctx = lookup_cpu_ctx(-1)) || !(tctx = lookup_task_ctx(p)) ||
!(layer = lookup_layer(tctx->layer)))
return;
if (tctx->last_cpu >= 0 && tctx->last_cpu != task_cpu)
if (tctx->last_cpu >= 0 && tctx->last_cpu != task_cpu) {
lstat_inc(LSTAT_MIGRATION, layer, cctx);
if (!(nodec = lookup_node_ctx(cctx->node_idx)))
return;
if (nodec->cpumask &&
!bpf_cpumask_test_cpu(tctx->last_cpu, nodec->cpumask))
lstat_inc(LSTAT_XNUMA_MIGRATION, layer, cctx);
if (!(cachec = lookup_cache_ctx(cctx->cache_idx)))
return;
if (cachec->cpumask &&
!bpf_cpumask_test_cpu(tctx->last_cpu, cachec->cpumask))
lstat_inc(LSTAT_XLLC_MIGRATION, layer, cctx);
}
tctx->last_cpu = task_cpu;
if (vtime_before(layer->vtime_now, p->scx.dsq_vtime))
@ -1560,6 +1645,11 @@ s32 BPF_STRUCT_OPS_SLEEPABLE(layered_init)
if (ret)
return ret;
}
bpf_for(i, 0, nr_llcs) {
ret = create_cache(i);
if (ret)
return ret;
}
dbg("CFG: Dumping configuration, nr_online_cpus=%d smt_enabled=%d",
nr_online_cpus, smt_enabled);

View File

@ -100,6 +100,10 @@ pub struct LayerStats {
pub yield_ignore: u64,
#[stat(desc = "% migrated across CPUs")]
pub migration: f64,
#[stat(desc = "% migrated across NUMA nodes")]
pub xnuma_migration: f64,
#[stat(desc = "% migrated across LLCs")]
pub xllc_migration: f64,
#[stat(desc = "mask of allocated CPUs", _om_skip)]
pub cpus: Vec<u32>,
#[stat(desc = "# of CPUs assigned")]
@ -189,6 +193,8 @@ impl LayerStats {
yielded: lstat_pct(bpf_intf::layer_stat_idx_LSTAT_YIELD),
yield_ignore: lstat(bpf_intf::layer_stat_idx_LSTAT_YIELD_IGNORE) as u64,
migration: lstat_pct(bpf_intf::layer_stat_idx_LSTAT_MIGRATION),
xnuma_migration: lstat_pct(bpf_intf::layer_stat_idx_LSTAT_XNUMA_MIGRATION),
xllc_migration: lstat_pct(bpf_intf::layer_stat_idx_LSTAT_XLLC_MIGRATION),
cpus: Self::bitvec_to_u32s(&layer.cpus),
cur_nr_cpus: layer.cpus.count_ones() as u32,
min_nr_cpus: nr_cpus_range.0 as u32,
@ -236,10 +242,12 @@ impl LayerStats {
writeln!(
w,
" {:<width$} open_idle={} mig={} affn_viol={}",
" {:<width$} open_idle={} mig={} xnuma_mig={} xllc_mig={} affn_viol={}",
"",
fmt_pct(self.open_idle),
fmt_pct(self.migration),
fmt_pct(self.xnuma_migration),
fmt_pct(self.xllc_migration),
fmt_pct(self.affn_viol),
width = header_width,
)?;