chpstat: Add options to select IEC units for scaling

Add options to select power-of-two based IEC units such as KiB/s
(1024 B/s) for scaling throughput values in human readable reports.

Option            Scaling factor
================================
--scale ki        1024
--scale mi        1048576
--scale gi        1073741824
--scale auto-iec  IEC units

Reviewed-by: Jimmy Brisson <jbrisson@linux.ibm.com>
Reviewed-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Signed-off-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
This commit is contained in:
Peter Oberparleiter
2025-08-20 14:54:18 +02:00
committed by Steffen Eiden
parent 4b76530788
commit d15e36cf24
4 changed files with 55 additions and 15 deletions
+22
View File
@@ -294,6 +294,12 @@ Scale automatically to fit value into each column. To indicate the current scali
an SI-suffix is added to each scaled number (e.g. K for 1000). This is the default.
.PP
.IP \(bu 3
.B auto-iec:
Same as
.B auto
but using power-of-two based IEC-suffixes (e.g. Ki for 1024).
.PP
.IP \(bu 3
.IR number :
Scale by
.I number
@@ -314,6 +320,22 @@ Scale by 1,000,000,000 (GB)
.B T:
Scale by 1,000,000,000,000 (TB)
.PP
.IP \(bu 3
.B Ki:
Scale by 1024 (KiB)
.PP
.IP \(bu 3
.B Mi:
Scale by 1,048,576 (MiB)
.PP
.IP \(bu 3
.B Gi:
Scale by 1,073,741,824 (GiB)
.PP
.IP \(bu 3
.B Ti:
Scale by 1,099,511,627,776 (TiB)
.PP
.RE
.BR \-\-cmg
+29 -13
View File
@@ -265,6 +265,7 @@ static struct {
unsigned long unit;
char unit_suffix;
bool unit_specified;
bool unit_iec;
} opts;
/* Per CHPID run-time data. */
@@ -336,6 +337,7 @@ static void init_opts(void)
opts.unit = UNIT_AUTO;
opts.unit_suffix = 0;
opts.unit_specified = false;
opts.unit_iec = false;
}
/*
@@ -459,23 +461,30 @@ static void parse_cmgs(char *arg)
}
}
static bool suffix_to_unit(char *arg, unsigned long *unit_ptr, char *suffix_ptr)
static bool suffix_to_unit(char *arg, unsigned long *unit_ptr, char *suffix_ptr,
bool *iec_ptr)
{
const char *suffixes = "KMGT";
unsigned long unit, base;
size_t len = strlen(arg);
char suffix;
bool iec;
int i;
if (len != 1)
if (len == 1)
iec = false;
else if (len == 2 && toupper(arg[1]) == 'I')
iec = true;
else
return false;
suffix = (char)toupper(*arg);
base = UNIT_DEC;
base = iec ? UNIT_BIN : UNIT_DEC;
unit = base;
for (i = 0; suffixes[i]; i++) {
if (suffix == suffixes[i]) {
*unit_ptr = unit;
*suffix_ptr = suffix;
*iec_ptr = iec;
return true;
}
unit *= base;
@@ -491,8 +500,12 @@ static unsigned long parse_unit(char *arg)
unsigned long unit;
char *endptr;
if (suffix_to_unit(arg, &unit, &opts.unit_suffix))
if (suffix_to_unit(arg, &unit, &opts.unit_suffix, &opts.unit_iec))
return unit;
if (strcmp(arg, "auto-iec") == 0) {
opts.unit_iec = true;
return UNIT_AUTO;
}
if (strcmp(arg, "auto") == 0)
return UNIT_AUTO;
/* Parse as number. */
@@ -1353,7 +1366,7 @@ static void scale_fixed(struct cmg_pair_t *p, unsigned long unit)
static void add_pair_value(struct util_rec *table, struct column_t *col,
struct cmg_pair_t *pair)
{
char suffix = 0, str[16];
char suffix = 0, suffix2 = opts.unit_iec ? 'i' : 0, str[16];
int p;
if (!pair->valid) {
@@ -1365,23 +1378,25 @@ static void add_pair_value(struct util_rec *table, struct column_t *col,
suffix = scale_auto(pair, UNIT_DEC);
} else if (pair->unit == CMG_BPS) {
if (opts.unit == UNIT_AUTO)
suffix = scale_auto(pair, UNIT_DEC);
suffix = scale_auto(pair, opts.unit_iec ? UNIT_BIN : UNIT_DEC);
else
scale_fixed(pair, opts.unit);
}
switch (pair->type) {
case CMG_U32:
snprintf(str, sizeof(str), "%u%c", pair->value_u32, suffix);
snprintf(str, sizeof(str), "%u%c%c", pair->value_u32, suffix,
suffix2);
break;
case CMG_U64:
snprintf(str, sizeof(str), "%llu%c", pair->value_u64, suffix);
snprintf(str, sizeof(str), "%llu%c%c", pair->value_u64, suffix,
suffix2);
break;
case CMG_FLOAT:
/* Find highest precision that fits into @width characters. */
for (p = 2; p >= 0; p--) {
snprintf(str, sizeof(str), "%.*f%c", p,
pair->value_double, suffix);
snprintf(str, sizeof(str), "%.*f%c%c", p,
pair->value_double, suffix, suffix2);
if (strlen(str) <= col->width)
break;
}
@@ -1681,8 +1696,8 @@ static void calc_column_widths(void)
width = 4; /* "999K" */
} else {
v = MAX_BPS / (double)opts.unit;
snprintf(str, sizeof(str) - 1, "%.0f%c", v,
opts.unit_suffix);
snprintf(str, sizeof(str) - 1, "%.0f%c%c", v,
opts.unit_suffix, opts.unit_iec ? 'i' : 0);
width = strlen_u(str);
}
break;
@@ -1707,7 +1722,8 @@ static void cmd_table(void)
apply_column_selection();
calc_column_widths();
column_update_bps_suffix(opts.unit == UNIT_AUTO, opts.unit_suffix);
column_update_bps_suffix(opts.unit == UNIT_AUTO, opts.unit_iec,
opts.unit_suffix);
printf("Collecting initial utilization data\n");
update_util_all(true);
+3 -1
View File
@@ -478,13 +478,15 @@ void column_select_all(void)
column_select(col);
}
void column_update_bps_suffix(bool auto_scale, char suffix_char)
void column_update_bps_suffix(bool auto_scale, bool iec, char suffix_char)
{
struct column_t *col;
char *str;
if (auto_scale)
util_asprintf(&str, "(B/s)");
else if (suffix_char && iec)
util_asprintf(&str, "(%ciB/s)", suffix_char);
else if (suffix_char)
util_asprintf(&str, "(%cB/s)", suffix_char);
else
+1 -1
View File
@@ -84,7 +84,7 @@ void column_select_id_list(const int *ids);
void column_select_default(void);
void column_select_all(void);
void column_update_bps_suffix(bool auto_scale, char suffix_char);
void column_update_bps_suffix(bool auto_scale, bool iec, char suffix_char);
void column_exit(void);
#endif /* COLUMN_H */