mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
hyptop: Calculate sample time delta for physical partition
Physical machine information does not include any monotonically increasing time field like other per CPU information blocks. This Prevents the percentage calculation for the physical information fields as the divisor(time_delta) is missing; field% = (value_current - value_previous) / time_delta To circumvent that, use the current partition's per CPU online time values to calculate the time_delta. Integrate time_delta as a new field(phys_delta_us) specific to the physical systems. Explicitly CPU0 online time is used, since CPU0 is always online and cannot be deconfigured on s390x. Its online-time deltas would match those of the physical CPUs. Since a new field has to be used for physical systems a new column in the table also has to be created but instead map the physical system field to the corresponding regular system fields for a nicer table view. Reviewed-by: Vasily Gorbik <gor@linux.ibm.com> Signed-off-by: Mete Durlu <meted@linux.ibm.com> Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
This commit is contained in:
committed by
Steffen Eiden
parent
1771e7f2f3
commit
0d6e63abdc
@@ -26,6 +26,7 @@
|
||||
#define CPU_TYPE_LEN 16
|
||||
#define DEBUGFS_FILE "diag_204"
|
||||
|
||||
static struct sd_sys *l_cur_lpar;
|
||||
static u64 l_update_time_us;
|
||||
static long l_204_buf_size;
|
||||
|
||||
@@ -36,7 +37,8 @@ static long l_204_buf_size;
|
||||
struct l_x_info_blk_hdr {
|
||||
u8 npar;
|
||||
u8 flags;
|
||||
u8 reserved1[6];
|
||||
u8 reserved1[4];
|
||||
u16 this_part;
|
||||
u64 curtod1;
|
||||
u64 curtod2;
|
||||
u8 reserved[40];
|
||||
@@ -158,6 +160,21 @@ static void *l_sd_sys_fill(struct sd_sys *lpar, struct l_x_sys_hdr *sys_hdr)
|
||||
return cpu_info;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the time delta between samples using current partition's
|
||||
* online time.
|
||||
*/
|
||||
static u64 l_sd_cur_lpar_delta_time_get(void)
|
||||
{
|
||||
struct sd_cpu *cpu;
|
||||
|
||||
cpu = sd_cpu_get(l_cur_lpar, "0");
|
||||
if (!cpu->d_prev || !cpu->d_cur)
|
||||
return 0;
|
||||
return l_sub_64(cpu->d_cur->online_time_us,
|
||||
cpu->d_prev->online_time_us);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill one physical CPU with data
|
||||
*/
|
||||
@@ -241,9 +258,9 @@ static void l_read_debugfs(struct l_debugfs_d204_hdr **hdr,
|
||||
*/
|
||||
static void l_sd_sys_root_fill(struct sd_sys *sys)
|
||||
{
|
||||
struct l_x_sys_hdr *sys_hdr, *this_part;
|
||||
struct l_x_info_blk_hdr *time_hdr;
|
||||
struct l_debugfs_d204_hdr *hdr;
|
||||
struct l_x_sys_hdr *sys_hdr;
|
||||
struct sd_sys *lpar;
|
||||
char lpar_id[10];
|
||||
int i;
|
||||
@@ -262,18 +279,23 @@ static void l_sd_sys_root_fill(struct sd_sys *sys)
|
||||
usleep(DBFS_WAIT_TIME_US);
|
||||
} while (1);
|
||||
sys_hdr = ((void *) time_hdr) + sizeof(struct l_x_info_blk_hdr);
|
||||
this_part = ((void *)time_hdr) + time_hdr->this_part;
|
||||
for (i = 0; i < time_hdr->npar; i++) {
|
||||
l_sys_hdr__sys_name(sys_hdr, lpar_id);
|
||||
lpar = sd_sys_get(sys, lpar_id);
|
||||
if (!lpar)
|
||||
lpar = sd_sys_new(sys, lpar_id);
|
||||
if (sys_hdr == this_part)
|
||||
l_cur_lpar = lpar;
|
||||
lpar->threads_per_core = l_thread_cnt(sys_hdr);
|
||||
sys_hdr = l_sd_sys_fill(lpar, sys_hdr);
|
||||
sd_sys_commit(lpar);
|
||||
}
|
||||
|
||||
if (time_hdr->flags & LPAR_PHYS_FLG)
|
||||
if (time_hdr->flags & LPAR_PHYS_FLG) {
|
||||
l_sd_sys_root_cpu_phys_fill(sys, (void *) sys_hdr);
|
||||
sd_phys_delta_time_us_set(sys, l_sd_cur_lpar_delta_time_get());
|
||||
}
|
||||
ht_free(hdr);
|
||||
sd_sys_commit(sys);
|
||||
}
|
||||
@@ -290,6 +312,16 @@ static void l_sd_update(void)
|
||||
sd_sys_update_end(root, l_update_time_us);
|
||||
}
|
||||
|
||||
/*
|
||||
* Supported physical information items
|
||||
*/
|
||||
static struct sd_sys_item *l_phys_item_vec[] = {
|
||||
&sd_sys_item_core_cnt,
|
||||
&sd_sys_item_phys_mgm_diff,
|
||||
&sd_sys_item_mgm,
|
||||
NULL,
|
||||
};
|
||||
|
||||
/*
|
||||
* Supported system items
|
||||
*/
|
||||
@@ -364,6 +396,7 @@ static struct sd_cpu_type *l_cpu_type_vec[] = {
|
||||
static struct sd_dg l_sd_dg = {
|
||||
.update_sys = l_sd_update,
|
||||
.cpu_type_vec = l_cpu_type_vec,
|
||||
.phys_item_vec = l_phys_item_vec,
|
||||
.sys_item_vec = l_sys_item_vec,
|
||||
.sys_item_enable_vec = l_sys_item_enable_vec,
|
||||
.cpu_item_vec = l_cpu_item_vec,
|
||||
|
||||
@@ -229,8 +229,10 @@ static void l_fmt_init(void)
|
||||
|
||||
if (!g.o.format_specified)
|
||||
return;
|
||||
if (g.o.format == FMT_CSV)
|
||||
if (g.o.format == FMT_CSV) {
|
||||
flags |= FMT_QUOTEALL;
|
||||
flags |= FMT_KEEPINVAL;
|
||||
}
|
||||
if (g.o.format == FMT_JSON || g.o.format == FMT_JSONSEQ)
|
||||
flags |= FMT_HANDLEINT;
|
||||
util_fmt_init(stdout, g.o.format, flags, 1);
|
||||
|
||||
12
hyptop/sd.h
12
hyptop/sd.h
@@ -78,6 +78,7 @@ struct sd_sys {
|
||||
struct util_list_node list;
|
||||
struct sd_info i;
|
||||
u64 update_time_us;
|
||||
u64 phys_delta_us;
|
||||
u32 child_cnt;
|
||||
u32 child_cnt_active;
|
||||
struct util_list child_list;
|
||||
@@ -135,6 +136,11 @@ static inline void sd_sys_update_time_us_set(struct sd_sys *sys, u64 value)
|
||||
sys->update_time_us = value;
|
||||
}
|
||||
|
||||
static inline void sd_phys_delta_time_us_set(struct sd_sys *sys, u64 value)
|
||||
{
|
||||
sys->phys_delta_us = value;
|
||||
}
|
||||
|
||||
/*
|
||||
* CPU type
|
||||
*/
|
||||
@@ -438,12 +444,15 @@ extern struct sd_sys_item sd_sys_item_os_name;
|
||||
extern struct sd_sys_item sd_sys_item_samples_total;
|
||||
extern struct sd_sys_item sd_sys_item_samples_cpu_using;
|
||||
|
||||
extern struct sd_sys_item sd_sys_item_phys_mgm_diff;
|
||||
|
||||
/*
|
||||
* Data gatherer backend
|
||||
*/
|
||||
struct sd_dg {
|
||||
void (*update_sys)(void);
|
||||
struct sd_cpu_type **cpu_type_vec;
|
||||
struct sd_sys_item **phys_item_vec;
|
||||
struct sd_sys_item **sys_item_vec;
|
||||
struct sd_sys_item **sys_item_enable_vec;
|
||||
struct sd_cpu_item **cpu_item_vec;
|
||||
@@ -463,6 +472,9 @@ int sd_dg_has_core_data(void);
|
||||
#define sd_cpu_iterate(parent, cpu) \
|
||||
util_list_iterate(&parent->cpu_list, cpu)
|
||||
|
||||
#define sd_phys_item_iterate(ptr, i) \
|
||||
for (i = 0; (ptr = sd.dg->phys_item_vec[i]); i++)
|
||||
|
||||
#define sd_sys_item_iterate(ptr, i) \
|
||||
for (i = 0; (ptr = sd.dg->sys_item_vec[i]); i++)
|
||||
|
||||
|
||||
@@ -220,9 +220,56 @@ static u64 l_sys_smt_util(struct sd_sys_item *item, struct sd_sys *sys)
|
||||
return ht_calculate_smt_util(core_us, thr_us, mgm_us, sys->threads_per_core);
|
||||
}
|
||||
|
||||
/*
|
||||
* value = (value_current - value_prev) / online_time_diff
|
||||
*/
|
||||
static double l_phys_cpu_info_diff_u64(struct sd_sys_item *item,
|
||||
struct sd_cpu *cpu,
|
||||
u64 time_diff_us)
|
||||
{
|
||||
double factor, diff_us;
|
||||
|
||||
if (!sd_cpu_type_selected(cpu->type))
|
||||
return 0;
|
||||
if (sd_cpu_state(cpu) == SD_CPU_STATE_STOPPED)
|
||||
return 0;
|
||||
if (time_diff_us == 0)
|
||||
return 0;
|
||||
diff_us = l_sub_64(l_cpu_info_u64(cpu->d_cur, item->offset),
|
||||
l_cpu_info_u64(cpu->d_prev, item->offset));
|
||||
factor = ((double)time_diff_us) / 1000000;
|
||||
diff_us /= factor;
|
||||
return diff_us;
|
||||
}
|
||||
|
||||
/*
|
||||
* SUM over all CPUs: value = (value_current - value_prev) / online_time_diff
|
||||
*/
|
||||
static u64 l_sys_phys_cpu_info_diff_u64(struct sd_sys_item *item, struct sd_sys *sys)
|
||||
{
|
||||
struct sd_cpu *cpu;
|
||||
u64 rc = 0;
|
||||
|
||||
sd_cpu_iterate(sys, cpu) {
|
||||
if (!cpu->d_prev || !cpu->d_cur)
|
||||
return 0;
|
||||
rc += l_phys_cpu_info_diff_u64(item, cpu, sys->phys_delta_us);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* System item definitions
|
||||
*/
|
||||
struct sd_sys_item sd_sys_item_phys_mgm_diff = {
|
||||
.table_col = TABLE_COL_TIME_DIFF_SUM(table_col_unit_perc, 'm', "mgm"),
|
||||
.offset = SD_CPU_INFO_OFFSET(mgm_time_us),
|
||||
.type = SD_TYPE_U64,
|
||||
.desc = "Management time per second",
|
||||
.fn_set = l_sys_cpu_info_set,
|
||||
.fn_u64 = l_sys_phys_cpu_info_diff_u64,
|
||||
};
|
||||
|
||||
struct sd_sys_item sd_sys_item_core_cnt = {
|
||||
.table_col = TABLE_COL_CNT_SUM('#', "#core"),
|
||||
.type = SD_TYPE_U32,
|
||||
|
||||
@@ -992,6 +992,8 @@ static void l_row_print_formatted(struct table *t, struct table_row *row)
|
||||
continue;
|
||||
if (table_col_needs_quotes(col))
|
||||
flags = FMT_QUOTE;
|
||||
if (strcmp(e->str, "-") == 0 || strcmp(e->str, "") == 0)
|
||||
flags |= FMT_INVAL;
|
||||
util_fmt_pair(flags, col->head, "%s", e->str);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,7 +170,7 @@ static void l_row_add_physical(struct table *t, struct sd_sys *sys)
|
||||
|
||||
row = table_row_alloc(t);
|
||||
table_row_entry_str_add(row, &l_col_sys, sd_sys_id(sys));
|
||||
sd_sys_item_iterate(item, i) {
|
||||
sd_phys_item_iterate(item, i) {
|
||||
if (!sd_sys_item_set(sys, item))
|
||||
continue;
|
||||
l_sys_item_add(row, sys, item);
|
||||
@@ -342,6 +342,11 @@ static void l_run(struct hyptop_win *win)
|
||||
}
|
||||
}
|
||||
|
||||
static void win_sys_list_set_phys_table_cols(void)
|
||||
{
|
||||
sd_sys_item_phys_mgm_diff.table_col = sd_sys_item_mgm_diff.table_col;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize window
|
||||
*/
|
||||
@@ -369,6 +374,8 @@ void win_sys_list_init(void)
|
||||
col_vec[i] = col;
|
||||
col_desc_vec[i] = item->desc;
|
||||
}
|
||||
if (sd_dg_has_phys_data())
|
||||
win_sys_list_set_phys_table_cols();
|
||||
/* Enable fields */
|
||||
if (win_sys_list.opts.fields.specified)
|
||||
l_fields_enable_cmdline();
|
||||
|
||||
Reference in New Issue
Block a user