From 2278f112ba019e8433837d3b3ac1aab8c5d5cf4a Mon Sep 17 00:00:00 2001 From: Thomas Richter Date: Wed, 26 Mar 2025 10:57:16 +0100 Subject: [PATCH] cpumf/lshwc: Add support for delta counter value display MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a flag to display the counter value in form of a delta value. This format shows the increase of that counter value in comparison to the previous readout. The first line is the base for the delta calculation and always shows 'Total'. The remaining lines show 'Delta' in the third column. # ./lshwc -d -i 3 -l 5 -x -s :p Date,Time,CPU,P32,P33 2024-11-27,15:45:55,Total,d7b,172 2024-11-27,15:45:58,Delta,2be403,2d58bb 2024-11-27,15:46:01,Delta,43e3b,22c41 2024-11-27,15:46:04,Delta,58e3a,35319 2024-11-27,15:46:07,Delta,5080e,2b81c # Signed-off-by: Thomas Richter Reviewed-by: Jan Höppner Signed-off-by: Jan Höppner --- cpumf/lshwc.c | 31 ++++++++++++++++++++++++++++--- cpumf/man/lshwc.8 | 29 ++++++++++++++++++++++++++++- 2 files changed, 56 insertions(+), 4 deletions(-) diff --git a/cpumf/lshwc.c b/cpumf/lshwc.c index aba27d36..d5868273 100644 --- a/cpumf/lshwc.c +++ b/cpumf/lshwc.c @@ -57,6 +57,7 @@ static bool allcpu; static char *ctrformat = "%ld"; static bool shortname; static bool hideundef; +static bool delta, firstread; static unsigned int max_possible_cpus; /* No of possible CPUs */ static struct ctrname { /* List of defined counters */ @@ -64,6 +65,7 @@ static struct ctrname { /* List of defined counters */ bool hitcnt; /* Counter number read from ioctl() */ unsigned long total; /* Total counter value */ unsigned long *ccv; /* Per CPU counter value */ + unsigned long *ccvprv; /* Per CPU counter value (previous read) */ } ctrname[MAXCTRS]; static char *mk_name(int ctr, char *name) @@ -129,6 +131,7 @@ static void free_counternames(void) for (size_t i = 0; i < ARRAY_SIZE(ctrname); ++i) { free(ctrname[i].name); free(ctrname[i].ccv); + free(ctrname[i].ccvprv); } } @@ -391,7 +394,7 @@ static void line(char *header) } /* Print total count of all CPUs */ - printf("%sTotal,", header); + printf("%s%s,", header, delta && !firstread ? "Delta" : "Total"); comma = false; for (size_t i = 0; i < ARRAY_SIZE(ctrname); ++i) { if (!ctrname[i].hitcnt) @@ -490,7 +493,18 @@ static bool add_countervalue(size_t idx, unsigned int cpu, unsigned long value) warnx("Invalid CPU number %d", cpu); return false; } - ctrname[idx].ccv[cpu] = value; + if (delta) { + if (firstread) { + ctrname[idx].ccvprv[cpu] = value; + ctrname[idx].ccv[cpu] = value; + } else { + ctrname[idx].ccv[cpu] = value - ctrname[idx].ccvprv[cpu]; + ctrname[idx].ccvprv[cpu] = value; + value = ctrname[idx].ccv[cpu]; + } + } else { + ctrname[idx].ccv[cpu] = value; + } ctrname[idx].total += value; ctrname[idx].hitcnt = true; return true; @@ -538,6 +552,7 @@ static int test_read(struct s390_hwctr_read *read) } } show(); + firstread = false; return 0; } @@ -665,6 +680,10 @@ static struct util_opt opt_vec[] = { .option = { "hide", no_argument, NULL, 'H' }, .desc = "Do not display undefined counters of a counter set" }, + { + .option = { "delta", no_argument, NULL, 'd' }, + .desc = "Display delta counter values" + }, UTIL_OPT_HELP, UTIL_OPT_VERSION, UTIL_OPT_END @@ -740,6 +759,10 @@ int main(int argc, char **argv) case 'a': allcpu = true; break; + case 'd': + delta = true; + firstread = true; + break; } } @@ -753,8 +776,10 @@ int main(int argc, char **argv) return EXIT_FAILURE; } - for (unsigned int i = 0; i < ARRAY_SIZE(ctrname); ++i) + for (unsigned int i = 0; i < ARRAY_SIZE(ctrname); ++i) { ctrname[i].ccv = util_zalloc(max_possible_cpus * sizeof(unsigned long)); + ctrname[i].ccvprv = util_zalloc(max_possible_cpus * sizeof(unsigned long)); + } if (optind >= argc) { ch = do_it(NULL); diff --git a/cpumf/man/lshwc.8 b/cpumf/man/lshwc.8 index 0d9ac7fc..c0dc2624 100644 --- a/cpumf/man/lshwc.8 +++ b/cpumf/man/lshwc.8 @@ -14,7 +14,7 @@ lshwc \- extract CPU Measurement Facilities counter sets . .SH SYNOPSIS \*c -.RB [ \-a ][ \-H][ \-s ][ \-x ][ \-X] +.RB [ \-a ][ \-d][ \-H][ \-s ][ \-x ][ \-X] .RB [ \-l .IR count ] .RB [ \-i @@ -51,6 +51,13 @@ Displays counter values from each CPU. The default is a total summary line of all counters from all CPUs. . .TP +.BR \-d ", " \-\-delta +Displays counter values in form of deltas. +Each counter value shows the increment to the previous output line. +Without this flag the total value of each counter is displayed. +See Examples. +. +.TP .BR \-i ", " \-\-interval \fI\ seconds\fP Specifies a time interval, in seconds, that the command waits between read operations. @@ -162,6 +169,26 @@ Date,Time,CPU,PROBLEM_STATE_CPU_CYCLES(32),PROBLEM_STATE_INSTRUCTIONS(33) 2021-04-01,11:56:47,Total,6432163447,2978400903 .ft .fi +.sp 1 +This example shows the counter values of the basic counter set +using delta output format. +.nf +.ft CW +.sp 1 +# lshwc -d -l 10 -i 5 -s :b +Date,Time,CPU,B0,B1,B2,B3,B4,B5 +2025-03-26,10:34:19,Total,208075,117287,1950,50548,1082,49609 +2025-03-26,10:34:24,Delta,85800055,70353492,590286,13228290,364034,12945804 +2025-03-26,10:34:29,Delta,70654751,60656797,483047,10838672,305703,10570868 +2025-03-26,10:34:34,Delta,81043162,69476160,587141,13228161,376662,12868298 +2025-03-26,10:34:39,Delta,73434017,62675417,524857,11787256,333966,11543649 +2025-03-26,10:34:44,Delta,68367967,58452919,506712,11370740,310785,10589883 +2025-03-26,10:34:49,Delta,70351947,57607764,507675,11433377,312433,10676243 +2025-03-26,10:34:54,Delta,77154817,65371168,562153,12671030,349750,12311061 +2025-03-26,10:34:59,Delta,88871882,75441201,655310,14875963,392530,13773130 +2025-03-26,10:35:04,Delta,83763472,71730813,609260,13643680,366992,12672405 +.ft +.fi .SH "SEE ALSO" .BR lscpumf (8) .BR chcpumf (8)