From f3d0c9c1f0890ed2e85409c45f0323340a143745 Mon Sep 17 00:00:00 2001 From: Sebastien Godard Date: Sat, 25 Sep 2010 07:38:57 +0200 Subject: [PATCH] Create a new activity (A_HUGE) for hugepages statistics. Hugepages statistics have been added as an additional output for memory activity by commit d7ed8d382140e2d709a6753fa44a0acfcba91a7e. Create a dedicated activity for them (A_HUGE). This is quite cleaner although the drawback is that /proc/meminfo file will be now read twice. --- activity.c | 31 +++++++++-- pr_stats.c | 134 +++++++++++++++++++++++++++++++++--------------- pr_stats.h | 4 ++ prf_stats.c | 101 ++++++++++++++++++++++++------------ prf_stats.h | 4 ++ rd_stats.c | 60 ++++++++++++++++------ rd_stats.h | 14 +++-- sa.h | 9 ++-- sa_common.c | 5 +- sa_wrap.c | 22 ++++++++ xml/sysstat.dtd | 8 ++- xml/sysstat.xsd | 14 +++-- 12 files changed, 298 insertions(+), 108 deletions(-) diff --git a/activity.c b/activity.c index 0f8644c..5c7843c 100644 --- a/activity.c +++ b/activity.c @@ -237,8 +237,7 @@ struct activity memory_act = { .f_xml_print = xml_print_memory_stats, .hdr_line = "frmpg/s;bufpg/s;campg/s|" "kbmemfree;kbmemused;%memused;kbbuffers;kbcached;kbcommit;%commit|" - "kbswpfree;kbswpused;%swpused;kbswpcad;%swpcad|" - "kbhugfree;kbhugused;%hugused", + "kbswpfree;kbswpused;%swpused;kbswpcad;%swpcad", .name = "A_MEMORY", #endif .nr = 1, @@ -934,6 +933,31 @@ struct activity pwr_in_act = { .bitmap = NULL }; +/* Hugepages activity */ +struct activity huge_act = { + .id = A_HUGE, + .options = AO_COLLECTED, +#ifdef SOURCE_SADC + .f_count = NULL, + .f_read = wrap_read_meminfo_huge, +#endif +#ifdef SOURCE_SAR + .f_print = print_huge_stats, + .f_print_avg = print_avg_huge_stats, +#endif +#ifdef SOURCE_SADF + .f_render = render_huge_stats, + .f_xml_print = xml_print_huge_stats, + .hdr_line = "kbhugfree;kbhugused;%hugused", + .name = "A_HUGE", +#endif + .nr = 1, + .fsize = STATS_HUGE_SIZE, + .msize = STATS_HUGE_SIZE, + .opt_flags = 0, + .buf = {NULL, NULL, NULL}, + .bitmap = NULL +}; /* * Array of activities. @@ -971,5 +995,6 @@ struct activity *act[NR_ACT] = { &pwr_cpufreq_act, &pwr_fan_act, &pwr_temp_act, - &pwr_in_act + &pwr_in_act, + &huge_act }; diff --git a/pr_stats.c b/pr_stats.c index 6109bf5..285055b 100644 --- a/pr_stats.c +++ b/pr_stats.c @@ -369,7 +369,7 @@ __print_funct_t print_io_stats(struct activity *a, int prev, int curr, /* *************************************************************************** - * Display memory, swap and huge pages statistics. This function is used to + * Display memory and swap statistics. This function is used to * display instantaneous and average statistics. * * IN: @@ -395,9 +395,6 @@ void stub_print_memory_stats(struct activity *a, int prev, int curr, avg_frskb = 0, avg_tlskb = 0, avg_caskb = 0; - static unsigned long long - avg_frhkb = 0, - avg_tlhkb = 0; if (DISPLAY_MEMORY(a->opt_flags)) { if (dis) { @@ -514,43 +511,6 @@ void stub_print_memory_stats(struct activity *a, int prev, int curr, avg_frskb = avg_tlskb = avg_caskb = 0; } } - - if (DISPLAY_HUGE(a->opt_flags)) { - if (dis) { - printf("\n%-11s kbhugfree kbhugused %%hugused\n", - timestamp[!curr]); - } - - if (!dispavg) { - /* Display instantaneous values */ - printf("%-11s %9lu %9lu %6.2f\n", - timestamp[curr], - smc->frhkb, - smc->tlhkb - smc->frhkb, - smc->tlhkb ? - SP_VALUE(smc->frhkb, smc->tlhkb, smc->tlhkb) : 0.0); - - /* Will be used to compute the average */ - avg_frhkb += smc->frhkb; - avg_tlhkb += smc->tlhkb; - } - else { - /* Display average values */ - printf("%-11s %9.0f %9.0f %6.2f\n", - timestamp[curr], - (double) avg_frhkb / avg_count, - ((double) avg_tlhkb / avg_count) - - ((double) avg_frhkb / avg_count), - ((double) (avg_tlhkb / avg_count)) ? - SP_VALUE((double) (avg_frhkb / avg_count), - (double) (avg_tlhkb / avg_count), - (double) (avg_tlhkb / avg_count)) : - 0.0); - - /* Reset average counters */ - avg_frhkb = avg_tlhkb = 0; - } - } } /* @@ -2165,3 +2125,95 @@ __print_funct_t print_avg_pwr_in_stats(struct activity *a, int prev, int curr, { stub_print_pwr_in_stats(a, prev, curr, TRUE); } + +/* + *************************************************************************** + * Display huge pages statistics. This function is used to + * display instantaneous and average statistics. + * + * IN: + * @a Activity structure with statistics. + * @prev Index in array where stats used as reference are. + * @curr Index in array for current sample statistics. + * @itv Interval of time in jiffies. + * @dispavg TRUE if displaying average statistics. + *************************************************************************** + */ +void stub_print_huge_stats(struct activity *a, int prev, int curr, + unsigned long long itv, int dispavg) +{ + struct stats_huge + *smc = (struct stats_huge *) a->buf[curr]; + static unsigned long long + avg_frhkb = 0, + avg_tlhkb = 0; + + if (dis) { + printf("\n%-11s kbhugfree kbhugused %%hugused\n", + timestamp[!curr]); + } + + if (!dispavg) { + /* Display instantaneous values */ + printf("%-11s %9lu %9lu %6.2f\n", + timestamp[curr], + smc->frhkb, + smc->tlhkb - smc->frhkb, + smc->tlhkb ? + SP_VALUE(smc->frhkb, smc->tlhkb, smc->tlhkb) : 0.0); + + /* Will be used to compute the average */ + avg_frhkb += smc->frhkb; + avg_tlhkb += smc->tlhkb; + } + else { + /* Display average values */ + printf("%-11s %9.0f %9.0f %6.2f\n", + timestamp[curr], + (double) avg_frhkb / avg_count, + ((double) avg_tlhkb / avg_count) - + ((double) avg_frhkb / avg_count), + ((double) (avg_tlhkb / avg_count)) ? + SP_VALUE((double) (avg_frhkb / avg_count), + (double) (avg_tlhkb / avg_count), + (double) (avg_tlhkb / avg_count)) : + 0.0); + + /* Reset average counters */ + avg_frhkb = avg_tlhkb = 0; + } +} + +/* + *************************************************************************** + * Display huge pages statistics. + * + * IN: + * @a Activity structure with statistics. + * @prev Index in array where stats used as reference are. + * @curr Index in array for current sample statistics. + * @itv Interval of time in jiffies. + *************************************************************************** + */ +__print_funct_t print_huge_stats(struct activity *a, int prev, int curr, + unsigned long long itv) +{ + stub_print_huge_stats(a, prev, curr, itv, FALSE); +} + +/* + *************************************************************************** + * Display huge pages statistics. + * + * IN: + * @a Activity structure with statistics. + * @prev Index in array where stats used as reference are. + * @curr Index in array for current sample statistics. + * @itv Interval of time in jiffies. + *************************************************************************** + */ +__print_funct_t print_avg_huge_stats(struct activity *a, int prev, int curr, + unsigned long long itv) +{ + stub_print_huge_stats(a, prev, curr, itv, TRUE); +} diff --git a/pr_stats.h b/pr_stats.h index 8f6c6d9..f847ee0 100644 --- a/pr_stats.h +++ b/pr_stats.h @@ -82,6 +82,8 @@ extern __print_funct_t print_pwr_temp_stats (struct activity *, int, int, unsigned long long); extern __print_funct_t print_pwr_in_stats (struct activity *, int, int, unsigned long long); +extern __print_funct_t print_huge_stats + (struct activity *, int, int, unsigned long long); /* Functions used to display average statistics */ extern __print_funct_t print_avg_memory_stats @@ -102,5 +104,7 @@ extern __print_funct_t print_avg_pwr_temp_stats (struct activity *, int, int, unsigned long long); extern __print_funct_t print_avg_pwr_in_stats (struct activity *, int, int, unsigned long long); +extern __print_funct_t print_avg_huge_stats + (struct activity *, int, int, unsigned long long); #endif /* _PR_STATS_H */ diff --git a/prf_stats.c b/prf_stats.c index 4bcdeef..59dbf68 100644 --- a/prf_stats.c +++ b/prf_stats.c @@ -616,7 +616,7 @@ __print_funct_t render_io_stats(struct activity *a, int isdb, char *pre, /* *************************************************************************** - * Display memory, swap and huge pages statistics in selected format. + * Display memory and swap statistics in selected format. * * IN: * @a Activity structure with statistics. @@ -717,23 +717,6 @@ __print_funct_t render_memory_stats(struct activity *a, int isdb, char *pre, SP_VALUE(0, smc->caskb, smc->tlskb - smc->frskb) : 0.0); } - - if (DISPLAY_HUGE(a->opt_flags)) { - - render(isdb, pre, PT_USEINT, - "-\tkbhugfree", NULL, NULL, - smc->frhkb, DNOVAL); - - render(isdb, pre, PT_USEINT, - "-\tkbhugused", NULL, NULL, - smc->tlhkb - smc->frhkb, DNOVAL); - - render(isdb, pre, pt_newlin, - "-\t%%hugused", NULL, NULL, NOVAL, - smc->tlhkb ? - SP_VALUE(smc->frhkb, smc->tlhkb, smc->tlhkb) : - 0.0); - } } /* @@ -2378,6 +2361,41 @@ __print_funct_t render_pwr_in_stats(struct activity *a, int isdb, char *pre, } } +/* + *************************************************************************** + * Display huge pages statistics in selected format. + * + * IN: + * @a Activity structure with statistics. + * @isdb Flag, true if db printing, false if ppc printing. + * @pre Prefix string for output entries + * @curr Index in array for current sample statistics. + * @itv Interval of time in jiffies. + *************************************************************************** + */ +__print_funct_t render_huge_stats(struct activity *a, int isdb, char *pre, + int curr, unsigned long long itv) +{ + struct stats_huge + *smc = (struct stats_huge *) a->buf[curr]; + int pt_newlin + = (DISPLAY_HORIZONTALLY(flags) ? PT_NOFLAG : PT_NEWLIN); + + render(isdb, pre, PT_USEINT, + "-\tkbhugfree", NULL, NULL, + smc->frhkb, DNOVAL); + + render(isdb, pre, PT_USEINT, + "-\tkbhugused", NULL, NULL, + smc->tlhkb - smc->frhkb, DNOVAL); + + render(isdb, pre, pt_newlin, + "-\t%%hugused", NULL, NULL, NOVAL, + smc->tlhkb ? + SP_VALUE(smc->frhkb, smc->tlhkb, smc->tlhkb) : + 0.0); +} + /* *************************************************************************** * Print tabulations @@ -2873,20 +2891,6 @@ __print_funct_t xml_print_memory_stats(struct activity *a, int curr, int tab, 0.0); } - if (DISPLAY_HUGE(a->opt_flags)) { - - xprintf(++tab, "%lu", - smc->frhkb); - - xprintf(tab, "%lu", - smc->tlhkb - smc->frhkb); - - xprintf(tab--, "%.2f", - smc->tlhkb ? - SP_VALUE(smc->frhkb, smc->tlhkb, smc->tlhkb) : - 0.0); - } - if (DISPLAY_MEMORY(a->opt_flags)) { xprintf(++tab, "%.2f", @@ -4193,3 +4197,36 @@ close_xml_markup: xml_markup_power_management(tab, CLOSE_XML_MARKUP); } } + +/* + *************************************************************************** + * Display huge pages statistics in XML. + * + * IN: + * @a Activity structure with statistics. + * @curr Index in array for current sample statistics. + * @tab Indentation in XML output. + * @itv Interval of time in jiffies. + *************************************************************************** + */ +__print_funct_t xml_print_huge_stats(struct activity *a, int curr, int tab, + unsigned long long itv) +{ + struct stats_huge + *smc = (struct stats_huge *) a->buf[curr]; + + xprintf(tab, ""); + + xprintf(++tab, "%lu", + smc->frhkb); + + xprintf(tab, "%lu", + smc->tlhkb - smc->frhkb); + + xprintf(tab--, "%.2f", + smc->tlhkb ? + SP_VALUE(smc->frhkb, smc->tlhkb, smc->tlhkb) : + 0.0); + + xprintf(tab, ""); +} diff --git a/prf_stats.h b/prf_stats.h index a24818f..71dde57 100644 --- a/prf_stats.h +++ b/prf_stats.h @@ -109,6 +109,8 @@ extern __print_funct_t render_pwr_temp_stats (struct activity *, int, char *, int, unsigned long long); extern __print_funct_t render_pwr_in_stats (struct activity *, int, char *, int, unsigned long long); +extern __print_funct_t render_huge_stats + (struct activity *, int, char *, int, unsigned long long); /* Functions used to display statistics in XML */ extern void xprintf @@ -179,5 +181,7 @@ extern __print_funct_t xml_print_pwr_temp_stats (struct activity *, int, int, unsigned long long); extern __print_funct_t xml_print_pwr_in_stats (struct activity *, int, int, unsigned long long); +extern __print_funct_t xml_print_huge_stats + (struct activity *, int, int, unsigned long long); #endif /* _PRF_STATS_H */ diff --git a/rd_stats.c b/rd_stats.c index ed9ba26..bf70da3 100644 --- a/rd_stats.c +++ b/rd_stats.c @@ -293,7 +293,6 @@ void read_meminfo(struct stats_memory *st_memory) { FILE *fp; char line[128]; - unsigned long szhkb = 0; if ((fp = fopen(MEMINFO, "r")) == NULL) return; @@ -332,25 +331,9 @@ void read_meminfo(struct stats_memory *st_memory) /* Read the amount of commited memory in kB */ sscanf(line + 13, "%lu", &st_memory->comkb); } - else if (!strncmp(line, "HugePages_Total:", 16)) { - /* Read the total number of huge pages */ - sscanf(line + 16, "%lu", &st_memory->tlhkb); - } - else if (!strncmp(line, "HugePages_Free:", 15)) { - /* Read the number of free huge pages */ - sscanf(line + 15, "%lu", &st_memory->frhkb); - } - else if (!strncmp(line, "Hugepagesize:", 13)) { - /* Read the default size of a huge page in kB */ - sscanf(line + 13, "%lu", &szhkb); - } } fclose(fp); - - /* We want huge pages stats in kB and not expressed in a number of pages */ - st_memory->tlhkb *= szhkb; - st_memory->frhkb *= szhkb; } /* @@ -2252,3 +2235,46 @@ void read_in(struct stats_pwr_in *st_pwr_in, int nbr) } #endif /* HAVE_SENSORS */ } + +/* + *************************************************************************** + * Read hugepages statistics from /proc/meminfo. + * + * IN: + * @st_huge Structure where stats will be saved. + * + * OUT: + * @st_huge Structure with statistics. + *************************************************************************** + */ +void read_meminfo_huge(struct stats_huge *st_huge) +{ + FILE *fp; + char line[128]; + unsigned long szhkb = 0; + + if ((fp = fopen(MEMINFO, "r")) == NULL) + return; + + while (fgets(line, 128, fp) != NULL) { + + if (!strncmp(line, "HugePages_Total:", 16)) { + /* Read the total number of huge pages */ + sscanf(line + 16, "%lu", &st_huge->tlhkb); + } + else if (!strncmp(line, "HugePages_Free:", 15)) { + /* Read the number of free huge pages */ + sscanf(line + 15, "%lu", &st_huge->frhkb); + } + else if (!strncmp(line, "Hugepagesize:", 13)) { + /* Read the default size of a huge page in kB */ + sscanf(line + 13, "%lu", &szhkb); + } + } + + fclose(fp); + + /* We want huge pages stats in kB and not expressed in a number of pages */ + st_huge->tlhkb *= szhkb; + st_huge->frhkb *= szhkb; +} diff --git a/rd_stats.h b/rd_stats.h index db1aaa0..559c82b 100644 --- a/rd_stats.h +++ b/rd_stats.h @@ -152,8 +152,6 @@ struct stats_memory { unsigned long tlskb __attribute__ ((aligned (8))); unsigned long caskb __attribute__ ((aligned (8))); unsigned long comkb __attribute__ ((aligned (8))); - unsigned long frhkb __attribute__ ((aligned (8))); - unsigned long tlhkb __attribute__ ((aligned (8))); }; #define STATS_MEMORY_SIZE (sizeof(struct stats_memory)) @@ -516,7 +514,15 @@ struct stats_pwr_in { char device[MAX_SENSORS_DEV_LEN] __attribute__ ((aligned (8))); }; -#define STATS_PWR_IN_SIZE (sizeof(struct stats_pwr_in)) +#define STATS_PWR_IN_SIZE (sizeof(struct stats_pwr_in)) + +/* Structure for hugepages statistics */ +struct stats_huge { + unsigned long frhkb __attribute__ ((aligned (8))); + unsigned long tlhkb __attribute__ ((aligned (8))); +}; + +#define STATS_HUGE_SIZE (sizeof(struct stats_memory)) /* *************************************************************************** @@ -593,6 +599,8 @@ extern void read_temp(struct stats_pwr_temp *, int); extern void read_in(struct stats_pwr_in *, int); +extern void + read_meminfo_huge(struct stats_huge *); /* *************************************************************************** diff --git a/sa.h b/sa.h index 91439da..e7c23a8 100644 --- a/sa.h +++ b/sa.h @@ -17,7 +17,7 @@ */ /* Number of activities */ -#define NR_ACT 33 +#define NR_ACT 34 /* Activities */ #define A_CPU 1 @@ -53,6 +53,7 @@ #define A_PWR_FAN 31 #define A_PWR_TEMP 32 #define A_PWR_IN 33 +#define A_HUGE 34 /* Macro used to flag an activity that should be collected */ @@ -94,16 +95,14 @@ #define DISPLAY_HORIZONTALLY(m) (((m) & S_F_HORIZONTALLY) == S_F_HORIZONTALLY) #define DISPLAY_COMMENT(m) (((m) & S_F_COMMENT) == S_F_COMMENT) -/* Output flags for options -R / -r / -S / -H */ +/* Output flags for options -R / -r / -S */ #define AO_F_MEM_DIA 0x00000001 #define AO_F_MEM_AMT 0x00000002 #define AO_F_MEM_SWAP 0x00000004 -#define AO_F_MEM_HUGE 0x00000008 #define DISPLAY_MEMORY(m) (((m) & AO_F_MEM_DIA) == AO_F_MEM_DIA) #define DISPLAY_MEM_AMT(m) (((m) & AO_F_MEM_AMT) == AO_F_MEM_AMT) #define DISPLAY_SWAP(m) (((m) & AO_F_MEM_SWAP) == AO_F_MEM_SWAP) -#define DISPLAY_HUGE(m) (((m) & AO_F_MEM_HUGE) == AO_F_MEM_HUGE) /* Output flags for option -u [ ALL ] */ #define AO_F_CPU_DEF 0x00000001 @@ -683,6 +682,8 @@ extern __read_funct_t wrap_read_temp(struct activity *); extern __read_funct_t wrap_read_in(struct activity *); +extern __read_funct_t + wrap_read_meminfo_huge(struct activity *); /* Other functions */ extern void diff --git a/sa_common.c b/sa_common.c index 2e14d50..8226ec2 100644 --- a/sa_common.c +++ b/sa_common.c @@ -1173,7 +1173,7 @@ int parse_sar_opt(char *argv[], int *opt, struct activity *act[], p = get_activity_position(act, A_MEMORY); act[p]->opt_flags |= AO_F_MEM_AMT + AO_F_MEM_DIA + - AO_F_MEM_SWAP + AO_F_MEM_HUGE; + AO_F_MEM_SWAP; p = get_activity_position(act, A_IRQ); set_bitmap(act[p]->bitmap->b_array, ~0, @@ -1202,9 +1202,8 @@ int parse_sar_opt(char *argv[], int *opt, struct activity *act[], break; case 'H': - p = get_activity_position(act, A_MEMORY); + p = get_activity_position(act, A_HUGE); act[p]->options |= AO_SELECTED; - act[p]->opt_flags |= AO_F_MEM_HUGE; break; case 'p': diff --git a/sa_wrap.c b/sa_wrap.c index 2c0daaf..8b758e3 100644 --- a/sa_wrap.c +++ b/sa_wrap.c @@ -873,6 +873,28 @@ __read_funct_t wrap_read_temp(struct activity *a) return; } +/* + *************************************************************************** + * Read hugepages statistics. + * + * IN: + * @a Activity structure. + * + * OUT: + * @a Activity structure with statistics. + *************************************************************************** + */ +__read_funct_t wrap_read_meminfo_huge(struct activity *a) +{ + struct stats_huge *st_huge + = (struct stats_huge *) a->_buf0; + + /* Read hugepages stats */ + read_meminfo_huge(st_huge); + + return; +} + /* *************************************************************************** * Get number of voltage input structures to allocate. diff --git a/xml/sysstat.dtd b/xml/sysstat.dtd index ade92ef..abab80b 100644 --- a/xml/sysstat.dtd +++ b/xml/sysstat.dtd @@ -98,13 +98,17 @@ pty-nr CDATA #REQUIRED > - + + + - + - - - @@ -56,6 +53,16 @@ + + + + + + + + + + @@ -609,6 +616,7 @@ + -- 2.40.0