From f7faa585fe0f462a69e9978dfb76662cfe3b97d5 Mon Sep 17 00:00:00 2001 From: Sebastien GODARD Date: Wed, 20 Mar 2019 10:47:23 +0100 Subject: [PATCH] sadf: PCP: Add support for A_MEMORY activity Add metrics displayed by "sar -r [ALL]" (memory statistics) to PCP archive. Signed-off-by: Sebastien GODARD --- activity.c | 1 + pcp_def_metrics.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++ pcp_def_metrics.h | 1 + pcp_stats.c | 105 +++++++++++++++++++++++++++++++++++++++++++++ pcp_stats.h | 2 + sadf_misc.c | 4 ++ 6 files changed, 219 insertions(+) diff --git a/activity.c b/activity.c index 6a76f39..e7c1504 100644 --- a/activity.c +++ b/activity.c @@ -367,6 +367,7 @@ struct activity memory_act = { .f_json_print = json_print_memory_stats, .f_svg_print = svg_print_memory_stats, .f_raw_print = raw_print_memory_stats, + .f_pcp_print = pcp_print_memory_stats, .f_count_new = NULL, .item_list = NULL, .desc = "Memory and/or swap utilization", diff --git a/pcp_def_metrics.c b/pcp_def_metrics.c index fd96cf4..2c9f552 100644 --- a/pcp_def_metrics.c +++ b/pcp_def_metrics.c @@ -165,6 +165,112 @@ void pcp_def_pcsw_metrics(void) #endif /* HAVE_PCP */ } +/* + *************************************************************************** + * Define PCP metrics for memory statistics. + * + * IN: + * @a Activity structure with statistics. + *************************************************************************** + */ +void pcp_def_memory_metrics(struct activity *a) +{ +#ifdef HAVE_PCP + if (DISPLAY_MEMORY(a->opt_flags)) { + + pmiAddMetric("mem.util.free", + PM_IN_NULL, PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_INSTANT, + pmiUnits(1, 0, 0, 0, PM_SPACE_KBYTE, 0)); + + pmiAddMetric("mem.util.available", + PM_IN_NULL, PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_INSTANT, + pmiUnits(1, 0, 0, 0, PM_SPACE_KBYTE, 0)); + + pmiAddMetric("mem.util.used", + PM_IN_NULL, PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_INSTANT, + pmiUnits(1, 0, 0, 0, PM_SPACE_KBYTE, 0)); + + pmiAddMetric("mem.util.used_pct", + PM_IN_NULL, PM_TYPE_FLOAT, PM_INDOM_NULL, PM_SEM_INSTANT, + pmiUnits(0, 0, 0, 0, 0, 0)); + + pmiAddMetric("mem.util.buffers", + PM_IN_NULL, PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_INSTANT, + pmiUnits(1, 0, 0, 0, PM_SPACE_KBYTE, 0)); + + pmiAddMetric("mem.util.cached", + PM_IN_NULL, PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_INSTANT, + pmiUnits(1, 0, 0, 0, PM_SPACE_KBYTE, 0)); + + pmiAddMetric("mem.util.commit", + PM_IN_NULL, PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_INSTANT, + pmiUnits(1, 0, 0, 0, PM_SPACE_KBYTE, 0)); + + pmiAddMetric("mem.util.commit_pct", + PM_IN_NULL, PM_TYPE_FLOAT, PM_INDOM_NULL, PM_SEM_INSTANT, + pmiUnits(0, 0, 0, 0, 0, 0)); + + pmiAddMetric("mem.util.active", + PM_IN_NULL, PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_INSTANT, + pmiUnits(1, 0, 0, 0, PM_SPACE_KBYTE, 0)); + + pmiAddMetric("mem.util.inactive", + PM_IN_NULL, PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_INSTANT, + pmiUnits(1, 0, 0, 0, PM_SPACE_KBYTE, 0)); + + pmiAddMetric("mem.util.dirty", + PM_IN_NULL, PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_INSTANT, + pmiUnits(1, 0, 0, 0, PM_SPACE_KBYTE, 0)); + + if (DISPLAY_MEM_ALL(a->opt_flags)) { + + pmiAddMetric("mem.util.anonpages", + PM_IN_NULL, PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_INSTANT, + pmiUnits(1, 0, 0, 0, PM_SPACE_KBYTE, 0)); + + pmiAddMetric("mem.util.slab", + PM_IN_NULL, PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_INSTANT, + pmiUnits(1, 0, 0, 0, PM_SPACE_KBYTE, 0)); + + pmiAddMetric("mem.util.stack", + PM_IN_NULL, PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_INSTANT, + pmiUnits(1, 0, 0, 0, PM_SPACE_KBYTE, 0)); + + pmiAddMetric("mem.util.pageTables", + PM_IN_NULL, PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_INSTANT, + pmiUnits(1, 0, 0, 0, PM_SPACE_KBYTE, 0)); + + pmiAddMetric("mem.util.vmused", + PM_IN_NULL, PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_INSTANT, + pmiUnits(1, 0, 0, 0, PM_SPACE_KBYTE, 0)); + } + } + + if (DISPLAY_SWAP(a->opt_flags)) { + + pmiAddMetric("mem.util.swapFree", + PM_IN_NULL, PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_INSTANT, + pmiUnits(1, 0, 0, 0, PM_SPACE_KBYTE, 0)); + + pmiAddMetric("mem.util.swapUsed", + PM_IN_NULL, PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_INSTANT, + pmiUnits(1, 0, 0, 0, PM_SPACE_KBYTE, 0)); + + pmiAddMetric("mem.util.swapUsed_pct", + PM_IN_NULL, PM_TYPE_FLOAT, PM_INDOM_NULL, PM_SEM_INSTANT, + pmiUnits(0, 0, 0, 0, 0, 0)); + + pmiAddMetric("mem.util.swapCached", + PM_IN_NULL, PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_INSTANT, + pmiUnits(1, 0, 0, 0, PM_SPACE_KBYTE, 0)); + + pmiAddMetric("mem.util.swapCached_pct", + PM_IN_NULL, PM_TYPE_FLOAT, PM_INDOM_NULL, PM_SEM_INSTANT, + pmiUnits(0, 0, 0, 0, 0, 0)); + } +#endif /* HAVE_PCP */ +} + /* *************************************************************************** * Define PCP metrics for queue and load statistics. diff --git a/pcp_def_metrics.h b/pcp_def_metrics.h index fc89526..c54c1fd 100644 --- a/pcp_def_metrics.h +++ b/pcp_def_metrics.h @@ -14,6 +14,7 @@ void pcp_def_cpu_metrics(struct activity *); void pcp_def_pcsw_metrics(void); +void pcp_def_memory_metrics(struct activity *); void pcp_def_queue_metrics(void); #endif /* _PCP_DEF_METRICS_H */ diff --git a/pcp_stats.c b/pcp_stats.c index 5fa818e..756892a 100644 --- a/pcp_stats.c +++ b/pcp_stats.c @@ -211,6 +211,111 @@ __print_funct_t pcp_print_pcsw_stats(struct activity *a, int curr, unsigned long #endif /* HAVE_PCP */ } +/* + *************************************************************************** + * Display memory statistics in PCP format. + * + * IN: + * @a Activity structure with statistics. + * @curr Index in array for current sample statistics. + * @itv Interval of time in 1/100th of a second. + * @record_hdr Record header for current sample. + *************************************************************************** + */ +__print_funct_t pcp_print_memory_stats(struct activity *a, int curr, unsigned long long itv, + struct record_header *record_hdr) +{ +#ifdef HAVE_PCP + char buf[64]; + struct stats_memory + *smc = (struct stats_memory *) a->buf[curr]; + unsigned long long nousedmem; + + if (DISPLAY_MEMORY(a->opt_flags)) { + + nousedmem = smc->frmkb + smc->bufkb + smc->camkb + smc->slabkb; + if (nousedmem > smc->tlmkb) { + nousedmem = smc->tlmkb; + } + + snprintf(buf, sizeof(buf), "%llu", smc->frmkb); + pmiPutValue("mem.util.free", NULL, buf); + + snprintf(buf, sizeof(buf), "%llu", smc->availablekb); + pmiPutValue("mem.util.available", NULL, buf); + + snprintf(buf, sizeof(buf), "%llu", smc->tlmkb - nousedmem); + pmiPutValue("mem.util.used", NULL, buf); + + snprintf(buf, sizeof(buf), "%f", + smc->tlmkb ? SP_VALUE(nousedmem, smc->tlmkb, smc->tlmkb) : 0.0); + pmiPutValue("mem.util.used_pct", NULL, buf); + + snprintf(buf, sizeof(buf), "%llu", smc->bufkb); + pmiPutValue("mem.util.buffers", NULL, buf); + + snprintf(buf, sizeof(buf), "%llu", smc->camkb); + pmiPutValue("mem.util.cached", NULL, buf); + + snprintf(buf, sizeof(buf), "%llu", smc->comkb); + pmiPutValue("mem.util.commit", NULL, buf); + + snprintf(buf, sizeof(buf), "%f", + (smc->tlmkb + smc->tlskb) ? SP_VALUE(0, smc->comkb, smc->tlmkb + smc->tlskb) + : 0.0); + pmiPutValue("mem.util.commit_pct", NULL, buf); + + snprintf(buf, sizeof(buf), "%llu", smc->activekb); + pmiPutValue("mem.util.active", NULL, buf); + + snprintf(buf, sizeof(buf), "%llu", smc->inactkb); + pmiPutValue("mem.util.inactive", NULL, buf); + + snprintf(buf, sizeof(buf), "%llu", smc->dirtykb); + pmiPutValue("mem.util.dirty", NULL, buf); + + if (DISPLAY_MEM_ALL(a->opt_flags)) { + + snprintf(buf, sizeof(buf), "%llu", smc->anonpgkb); + pmiPutValue("mem.util.anonpages", NULL, buf); + + snprintf(buf, sizeof(buf), "%llu", smc->slabkb); + pmiPutValue("mem.util.slab", NULL, buf); + + snprintf(buf, sizeof(buf), "%llu", smc->kstackkb); + pmiPutValue("mem.util.stack", NULL, buf); + + snprintf(buf, sizeof(buf), "%llu", smc->pgtblkb); + pmiPutValue("mem.util.pageTables", NULL, buf); + + snprintf(buf, sizeof(buf), "%llu", smc->vmusedkb); + pmiPutValue("mem.util.vmused", NULL, buf); + } + } + + if (DISPLAY_SWAP(a->opt_flags)) { + + snprintf(buf, sizeof(buf), "%llu", smc->frskb); + pmiPutValue("mem.util.swapFree", NULL, buf); + + snprintf(buf, sizeof(buf), "%llu", smc->tlskb - smc->frskb); + pmiPutValue("mem.util.swapUsed", NULL, buf); + + snprintf(buf, sizeof(buf), "%f", + smc->tlskb ? SP_VALUE(smc->frskb, smc->tlskb, smc->tlskb) : 0.0); + pmiPutValue("mem.util.swapUsed_pct", NULL, buf); + + snprintf(buf, sizeof(buf), "%llu", smc->caskb); + pmiPutValue("mem.util.swapCached", NULL, buf); + + snprintf(buf, sizeof(buf), "%f", + (smc->tlskb - smc->frskb) ? SP_VALUE(0, smc->caskb, smc->tlskb - smc->frskb) + : 0.0); + pmiPutValue("mem.util.swapCached_pct", NULL, buf); + } +#endif /* HAVE_PCP */ +} + /* *************************************************************************** * Display queue and load statistics in PCP format diff --git a/pcp_stats.h b/pcp_stats.h index 1e266ae..b73fb17 100644 --- a/pcp_stats.h +++ b/pcp_stats.h @@ -17,6 +17,8 @@ __print_funct_t pcp_print_cpu_stats (struct activity *, int, unsigned long long, struct record_header *); __print_funct_t pcp_print_pcsw_stats (struct activity *, int, unsigned long long, struct record_header *); +__print_funct_t pcp_print_memory_stats + (struct activity *, int, unsigned long long, struct record_header *); __print_funct_t pcp_print_queue_stats (struct activity *, int, unsigned long long, struct record_header *); diff --git a/sadf_misc.c b/sadf_misc.c index 9acf2ae..ef124de 100644 --- a/sadf_misc.c +++ b/sadf_misc.c @@ -505,6 +505,10 @@ __printf_funct_t print_pcp_statistics(int *tab, int action, struct activity *act pcp_def_pcsw_metrics(); break; + case A_MEMORY: + pcp_def_memory_metrics(act[p]); + break; + case A_QUEUE: pcp_def_queue_metrics(); break; -- 2.40.0