diff options
author | Jason King <jason.king@joyent.com> | 2018-11-01 12:47:21 -0500 |
---|---|---|
committer | Jason King <jason.king@joyent.com> | 2020-12-08 19:13:03 +0000 |
commit | b56d7ba70c13eb53c9a274b4d47e3317fe87a716 (patch) | |
tree | 9623ce551f5fb6d91494ed0fb958030a67dd7435 | |
parent | 88880f2384ccc4a2382a0fd56138ff5a6862866f (diff) | |
download | illumos-joyent-b56d7ba70c13eb53c9a274b4d47e3317fe87a716.tar.gz |
More load calculations
-rw-r--r-- | usr/src/cmd/intrd/intrd.c | 48 | ||||
-rw-r--r-- | usr/src/cmd/intrd/intrd.h | 18 |
2 files changed, 59 insertions, 7 deletions
diff --git a/usr/src/cmd/intrd/intrd.c b/usr/src/cmd/intrd/intrd.c index fa0ef14e45..4eb84461b3 100644 --- a/usr/src/cmd/intrd/intrd.c +++ b/usr/src/cmd/intrd/intrd.c @@ -218,18 +218,19 @@ setup(kstat_ctl_t **restrict kcpp, config_t *restrict cfg) // XXX: Initialize cfg } +/* + * Temporary functions to output data during development. Maybe turn into + * debug output later. + */ static void format_load(lgrp_id_t id, load_t *l, int indent) { char buf[NN_NUMBUF_SZ]; - double pct = 0.0; nanonicenum(l->ld_intrtotal, buf, sizeof (buf)); - if (l->ld_total > 0) - pct = (double)(l->ld_intrtotal * 100) / l->ld_total; (void) printf("%*sLGRP %2d %zu CPUs intr %6ss (%3.1f%%)", - indent * 2, "", id, l->ld_ncpu, buf, pct); + indent * 2, "", id, l->ld_ncpu, buf, l->ld_avgload * 100.0); ivec_t *iv = l->ld_bigint; @@ -350,12 +351,39 @@ delta_save(stats_t **deltas, size_t n, stats_t *newdelta, uint_t statslen) } static void +calc_avgs(load_t *ld) +{ + double intr = (double)ld->ld_intrtotal; + + if (ld->ld_ncpu == 0) { + ld->ld_avgnsec = 0.0; + ld->ld_avgload = 0.0; + return; + } + + ld->ld_avgnsec = intr; + ld->ld_avgload = intr / ld->ld_total; + + if (ld->ld_ncpu > 1) { + ld->ld_avgnsec /= ld->ld_ncpu; + ld->ld_avgload /= ld->ld_ncpu; + } +} + +static void calc_lgrp_load(cpugrp_t *grp, load_t *ld, lgrp_id_t id) { cpugrp_t *cg = grp + id; load_t *lgrp = LOAD_LGRP(ld, id); for (size_t i = 0; i < cg->cg_nchildren; i++) { + /* + * The values of an lgrp load_t entry are the sums of all + * the children lgrps (for ld_bigint, it is the interrupt + * consuming the most time in any of the child lgrps) of + * this lgrp. Recursively calculate any children first so + * their values are calculated before we calculate ours. + */ calc_lgrp_load(grp, ld, cg->cg_children[i]); load_t *lchild = LOAD_LGRP(ld, cg->cg_children[i]); @@ -365,6 +393,7 @@ calc_lgrp_load(cpugrp_t *grp, load_t *ld, lgrp_id_t id) lgrp->ld_bigint = LOAD_MAXINT(lgrp, lchild); lgrp->ld_ncpu += lchild->ld_ncpu; } + calc_avgs(lgrp); } static intrd_walk_ret_t @@ -385,6 +414,7 @@ calc_load_cb(stats_t *stp, cpustat_t *cs, void *arg) if (LOAD_BIGINT_LOAD(lcpu) < iv->ivec_time) lcpu->ld_bigint = iv; } + calc_avgs(lcpu); load_t *lgrp = LOAD_LGRP(load, cs->cs_lgrp); @@ -395,11 +425,21 @@ calc_load_cb(stats_t *stp, cpustat_t *cs, void *arg) return (INTRD_WALK_NEXT); } + static load_t * calc_load(stats_t *stp) { load_t *ld = xcalloc(max_cpu + stp->sts_nlgrp, sizeof (load_t)); + /* + * Calculate the load_t values for all the CPU entries first. If one + * thinks of the locality topology as a tree, the leaf lgrps (ones + * without any child lgrps) are the ones that will directly contain + * CPUs (these are also the lgrp_id_t values stored in + * cpustat_t->cs_lgrp). We also calculate those lgrp leaves at the same + * time we are calculating the per-CPU values in calc_load_cb(). + * We can then calculate any parent lgrps in calc_lgrp_load(). + */ VERIFY3S(cpu_iter(stp, calc_load_cb, ld), ==, INTRD_WALK_DONE); calc_lgrp_load(stp->sts_lgrp, ld, 0); return (ld); diff --git a/usr/src/cmd/intrd/intrd.h b/usr/src/cmd/intrd/intrd.h index 3bc00d2ec3..8f57acb6cb 100644 --- a/usr/src/cmd/intrd/intrd.h +++ b/usr/src/cmd/intrd/intrd.h @@ -42,6 +42,8 @@ typedef struct config { /* * An interrupt vector, corresponding to the data from a pci_intrs kstat. + * For shared interrupts, this may also represent a consolidated picture of + * all of those shared interrupts. */ typedef struct ivec { list_node_t ivec_node; @@ -78,7 +80,9 @@ typedef struct cpustat { } cpustat_t; /* - * The locality group data. + * The locality group data. Since NLGRPS_MAX is only available in the kernel + * and not userland, the array holding the IDs of the children of any lgrp + * is dynamically allocated. */ typedef struct cpugrp { lgrp_id_t cg_id; @@ -93,9 +97,13 @@ typedef struct cpugrp { * sts_{min,max}time represent the smallest and largest values of * kstat_t.ks_crtime of all the individual kstats used to create this snapshot. * - * cpustat_t's are indexed by CPU id. That is, the cpustat_t for CPU 5 is + * cpustat_t's are indexed by CPU id. For example, the cpustat_t for CPU 5 is * sts_cpu[5] -- i.e. there may be gaps in this. It is sized to hold * max_cpu (i.e. _SC_N_PROCESSORS_MAX) cpustat_t *'s. + * + * It also includes a snapshot of the locality groups near in time to when + * the kstats for this stats_t were read (i.e. we read the kstats, then grab + * the lgrp info). */ typedef struct stats { kid_t sts_kid; @@ -117,11 +125,15 @@ typedef struct stats { * total time, as well as the average interrupt time per cpu. In addition, * we keep a reference to ivec consuming the most time. A load_t is created * per cpu, as well as per locality group. The load_t's for lgrps are - * aggregated over all the cpus in a given lgrp. + * aggregated over all the cpus in a given lgrp. The results are stored in + * an array of load_t's where the first max_cpu entries represent the load of + * the corresponding CPU, followed by the locality groups. */ typedef struct load { uint64_t ld_total; uint64_t ld_intrtotal; + double ld_avgnsec; + double ld_avgload; ivec_t *ld_bigint; size_t ld_ncpu; } load_t; |