From 435d195a9da120c5a618129cdb73418f4748c20a Mon Sep 17 00:00:00 2001 From: Vincent Kang Fu Date: Wed, 6 Feb 2013 08:43:40 +0100 Subject: [PATCH] Handle percentile lists with higher precision that 2 digits We cap the output at %2.2f right now, that's not always enough. Make the parser check and store the precision required to output the list correctly. Signed-off-by: Jens Axboe --- fio.h | 1 + init.c | 1 + options.c | 1 + parse.c | 33 ++++++++++++++++++++++++++++++++- stat.c | 19 ++++++++++++------- stat.h | 1 + 6 files changed, 48 insertions(+), 8 deletions(-) diff --git a/fio.h b/fio.h index 370ddaad..43f48543 100644 --- a/fio.h +++ b/fio.h @@ -248,6 +248,7 @@ struct thread_options { unsigned int trim_zero; unsigned long long trim_backlog; unsigned int clat_percentiles; + unsigned int percentile_precision; /* digits after decimal for percentiles */ fio_fp64_t percentile_list[FIO_IO_U_LIST_MAX_LEN]; char *read_iolog_file; diff --git a/init.c b/init.c index 52665f02..60ba2993 100644 --- a/init.c +++ b/init.c @@ -867,6 +867,7 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num) td->mutex = fio_mutex_init(FIO_MUTEX_LOCKED); td->ts.clat_percentiles = td->o.clat_percentiles; + td->ts.percentile_precision = td->o.percentile_precision; memcpy(td->ts.percentile_list, td->o.percentile_list, sizeof(td->o.percentile_list)); for (i = 0; i < DDIR_RWDIR_CNT; i++) { diff --git a/options.c b/options.c index 4522fe45..42a2ea07 100644 --- a/options.c +++ b/options.c @@ -2434,6 +2434,7 @@ static struct fio_option options[FIO_MAX_OPTS] = { .name = "percentile_list", .type = FIO_OPT_FLOAT_LIST, .off1 = td_var_offset(percentile_list), + .off2 = td_var_offset(percentile_precision), .help = "Specify a custom list of percentiles to report", .def = "1:5:10:20:30:40:50:60:70:80:90:95:99:99.5:99.9:99.95:99.99", .maxlen = FIO_IO_U_LIST_MAX_LEN, diff --git a/parse.c b/parse.c index 4ce29c1f..15aeb0ac 100644 --- a/parse.c +++ b/parse.c @@ -369,10 +369,11 @@ static int __handle_option(struct fio_option *o, const char *ptr, void *data, long ul1, ul2; double uf; char **cp = NULL; + char *cp2; int ret = 0, is_time = 0; const struct value_pair *vp; struct value_pair posval[PARSE_MAX_VP]; - int i, all_skipped = 1; + int i, len, all_skipped = 1; dprint(FD_PARSE, "__handle_option=%s, type=%d, ptr=%s\n", o->name, o->type, ptr); @@ -502,6 +503,19 @@ static int __handle_option(struct fio_option *o, const char *ptr, void *data, break; } case FIO_OPT_FLOAT_LIST: { + if (first) { + /* + ** Initialize precision to 0 and zero out list + ** in case specified list is shorter than default + */ + ul2 = 0; + ilp = td_var(data, o->off2); + *ilp = ul2; + + flp = td_var(data, o->off1); + for(i = 0; i < o->maxlen; i++) + flp[i].u.f = 0.0; + } if (curr >= o->maxlen) { log_err("the list exceeding max length %d\n", o->maxlen); @@ -525,6 +539,23 @@ static int __handle_option(struct fio_option *o, const char *ptr, void *data, flp = td_var(data, o->off1); flp[curr].u.f = uf; + /* + ** Calculate precision for output by counting + ** number of digits after period. Find first + ** period in entire remaining list each time + */ + cp2 = strchr(ptr, '.'); + if (cp2 != NULL) { + len = 0; + + while (*++cp2 != '\0' && *cp2 >= '0' && *cp2 <= '9') + len++; + + ilp = td_var(data, o->off2); + if (len > *ilp) + *ilp = len; + } + break; } case FIO_OPT_STR_STORE: { diff --git a/stat.c b/stat.c index fb5ff64f..c523f5c2 100644 --- a/stat.c +++ b/stat.c @@ -182,11 +182,12 @@ static unsigned int calc_clat_percentiles(unsigned int *io_u_plat, * Find and display the p-th percentile of clat */ static void show_clat_percentiles(unsigned int *io_u_plat, unsigned long nr, - fio_fp64_t *plist) + fio_fp64_t *plist, uint64_t precision) { unsigned int len, j = 0, minv, maxv; unsigned int *ovals; int is_last, scale_down; + char buf1[32], buf2[32]; len = calc_clat_percentiles(io_u_plat, nr, plist, &ovals, &maxv, &minv); if (!len) @@ -204,8 +205,10 @@ static void show_clat_percentiles(unsigned int *io_u_plat, unsigned long nr, log_info(" clat percentiles (usec):\n |"); } + snprintf(buf1, sizeof(buf1), " %%1.%luf", precision); + snprintf(buf2, sizeof(buf1), "%%1.%luf", precision); for (j = 0; j < len; j++) { - char fbuf[8]; + char fbuf[16]; /* for formatting */ if (j != 0 && (j % 4) == 0) @@ -215,9 +218,9 @@ static void show_clat_percentiles(unsigned int *io_u_plat, unsigned long nr, is_last = (j == len - 1); if (plist[j].u.f < 10.0) - sprintf(fbuf, " %2.2f", plist[j].u.f); + snprintf(fbuf, sizeof(fbuf), buf1, plist[j].u.f); else - sprintf(fbuf, "%2.2f", plist[j].u.f); + snprintf(fbuf, sizeof(fbuf), buf2, plist[j].u.f); if (scale_down) ovals[j] = (ovals[j] + 999) / 1000; @@ -440,7 +443,8 @@ static void show_ddir_status(struct group_run_stats *rs, struct thread_stat *ts, if (ts->clat_percentiles) { show_clat_percentiles(ts->io_u_plat[ddir], ts->clat_stat[ddir].samples, - ts->percentile_list); + ts->percentile_list, + ts->percentile_precision); } if (calc_lat(&ts->bw_stat[ddir], &min, &max, &mean, &dev)) { double p_of_agg = 100.0; @@ -655,7 +659,7 @@ static void show_ddir_status_terse(struct thread_stat *ts, log_info(";0%%=0"); continue; } - log_info(";%2.2f%%=%u", ts->percentile_list[i].u.f, ovals[i]); + log_info(";%f%%=%u", ts->percentile_list[i].u.f, ovals[i]); } if (calc_lat(&ts->lat_stat[ddir], &min, &max, &mean, &dev)) @@ -753,7 +757,7 @@ static void add_ddir_status_json(struct thread_stat *ts, json_object_add_value_int(percentile_object, "0.00", 0); continue; } - snprintf(buf, sizeof(buf), "%2.2f", ts->percentile_list[i].u.f); + snprintf(buf, sizeof(buf), "%f", ts->percentile_list[i].u.f); json_object_add_value_int(percentile_object, (const char *)buf, ovals[i]); } @@ -1210,6 +1214,7 @@ void show_run_stats(void) ts = &threadstats[j]; ts->clat_percentiles = td->o.clat_percentiles; + ts->percentile_precision = td->o.percentile_precision; memcpy(ts->percentile_list, td->o.percentile_list, sizeof(td->o.percentile_list)); idx++; diff --git a/stat.h b/stat.h index 97186c18..98ae4c8e 100644 --- a/stat.h +++ b/stat.h @@ -144,6 +144,7 @@ struct thread_stat { * IO depth and latency stats */ uint64_t clat_percentiles; + uint64_t percentile_precision; fio_fp64_t percentile_list[FIO_IO_U_LIST_MAX_LEN]; uint32_t io_u_map[FIO_IO_U_MAP_NR]; -- 2.25.1