{
unsigned long long sum = 0;
unsigned int len, i, j = 0;
- unsigned int oval_len = 0;
unsigned long long *ovals = NULL;
bool is_last;
if (len > 1)
qsort((void *)plist, len, sizeof(plist[0]), double_cmp);
+ ovals = malloc(len * sizeof(*ovals));
+ if (!ovals)
+ return 0;
+
/*
* Calculate bucket values, note down max and min values
*/
is_last = false;
for (i = 0; i < FIO_IO_U_PLAT_NR && !is_last; i++) {
sum += io_u_plat[i];
- while (sum >= (plist[j].u.f / 100.0 * nr)) {
+ while (sum >= ((long double) plist[j].u.f / 100.0 * nr)) {
assert(plist[j].u.f <= 100.0);
- if (j == oval_len) {
- oval_len += 100;
- ovals = realloc(ovals, oval_len * sizeof(*ovals));
- }
-
ovals[j] = plat_idx_to_val(i);
if (ovals[j] < *minv)
*minv = ovals[j];
}
}
+ if (!is_last)
+ log_err("fio: error calculating latency percentiles\n");
+
*output = ovals;
return len;
}
unsigned long runt;
unsigned long long min, max, bw, iops;
double mean, dev;
- char *io_p, *bw_p, *bw_p_alt, *iops_p, *zbd_w_st = NULL;
+ char *io_p, *bw_p, *bw_p_alt, *iops_p, *post_st = NULL;
int i2p;
if (ddir_sync(ddir)) {
iops = (1000 * (uint64_t)ts->total_io_u[ddir]) / runt;
iops_p = num2str(iops, ts->sig_figs, 1, 0, N2S_NONE);
if (ddir == DDIR_WRITE)
- zbd_w_st = zbd_write_status(ts);
+ post_st = zbd_write_status(ts);
+ else if (ddir == DDIR_READ && ts->cachehit && ts->cachemiss) {
+ uint64_t total;
+ double hit;
+
+ total = ts->cachehit + ts->cachemiss;
+ hit = (double) ts->cachehit / (double) total;
+ hit *= 100.0;
+ if (asprintf(&post_st, "; Cachehit=%0.2f%%", hit) < 0)
+ post_st = NULL;
+ }
log_buf(out, " %s: IOPS=%s, BW=%s (%s)(%s/%llumsec)%s\n",
rs->unified_rw_rep ? "mixed" : io_ddir_name(ddir),
iops_p, bw_p, bw_p_alt, io_p,
(unsigned long long) ts->runtime[ddir],
- zbd_w_st ? : "");
+ post_st ? : "");
- free(zbd_w_st);
+ free(post_st);
free(io_p);
free(bw_p);
free(bw_p_alt);
len = 0;
percentile_object = json_create_object();
- json_object_add_value_object(tmp_object, "percentile", percentile_object);
+ if (ts->clat_percentiles)
+ json_object_add_value_object(tmp_object, "percentile", percentile_object);
for (i = 0; i < len; i++) {
snprintf(buf, sizeof(buf), "%f", ts->percentile_list[i].u.f);
json_object_add_value_int(percentile_object, (const char *)buf, ovals[i]);
json_object_add_value_int(tmp_object, "max", max);
json_object_add_value_float(tmp_object, "mean", mean);
json_object_add_value_float(tmp_object, "stddev", dev);
+ if (ts->lat_percentiles)
+ json_object_add_value_object(tmp_object, "percentile", percentile_object);
if (output_format & FIO_OUTPUT_JSON_PLUS && ts->lat_percentiles)
json_object_add_value_object(tmp_object, "bins", clat_bins_object);
json_object_add_value_float(dir_object, "iops_stddev", dev);
json_object_add_value_int(dir_object, "iops_samples",
(&ts->iops_stat[ddir])->samples);
+
+ if (ts->cachehit + ts->cachemiss) {
+ uint64_t total;
+ double hit;
+
+ total = ts->cachehit + ts->cachemiss;
+ hit = (double) ts->cachehit / (double) total;
+ hit *= 100.0;
+ json_object_add_value_float(dir_object, "cachehit", hit);
+ }
}
static void show_thread_status_terse_all(struct thread_stat *ts,
return ret;
}
-static void sum_stat(struct io_stat *dst, struct io_stat *src, bool first)
+static void __sum_stat(struct io_stat *dst, struct io_stat *src, bool first)
{
double mean, S;
- if (src->samples == 0)
- return;
-
dst->min_val = min(dst->min_val, src->min_val);
dst->max_val = max(dst->max_val, src->max_val);
dst->samples += src->samples;
dst->mean.u.f = mean;
dst->S.u.f = S;
+
+}
+
+/*
+ * We sum two kinds of stats - one that is time based, in which case we
+ * apply the proper summing technique, and then one that is iops/bw
+ * numbers. For group_reporting, we should just add those up, not make
+ * them the mean of everything.
+ */
+static void sum_stat(struct io_stat *dst, struct io_stat *src, bool first,
+ bool pure_sum)
+{
+ if (src->samples == 0)
+ return;
+
+ if (!pure_sum) {
+ __sum_stat(dst, src, first);
+ return;
+ }
+
+ if (first) {
+ dst->min_val = src->min_val;
+ dst->max_val = src->max_val;
+ dst->samples = src->samples;
+ dst->mean.u.f = src->mean.u.f;
+ dst->S.u.f = src->S.u.f;
+ } else {
+ dst->min_val += src->min_val;
+ dst->max_val += src->max_val;
+ dst->samples += src->samples;
+ dst->mean.u.f += src->mean.u.f;
+ dst->S.u.f += src->S.u.f;
+ }
}
void sum_group_stats(struct group_run_stats *dst, struct group_run_stats *src)
for (l = 0; l < DDIR_RWDIR_CNT; l++) {
if (!dst->unified_rw_rep) {
- sum_stat(&dst->clat_stat[l], &src->clat_stat[l], first);
- sum_stat(&dst->slat_stat[l], &src->slat_stat[l], first);
- sum_stat(&dst->lat_stat[l], &src->lat_stat[l], first);
- sum_stat(&dst->bw_stat[l], &src->bw_stat[l], first);
- sum_stat(&dst->iops_stat[l], &src->iops_stat[l], first);
+ sum_stat(&dst->clat_stat[l], &src->clat_stat[l], first, false);
+ sum_stat(&dst->slat_stat[l], &src->slat_stat[l], first, false);
+ sum_stat(&dst->lat_stat[l], &src->lat_stat[l], first, false);
+ sum_stat(&dst->bw_stat[l], &src->bw_stat[l], first, true);
+ sum_stat(&dst->iops_stat[l], &src->iops_stat[l], first, true);
dst->io_bytes[l] += src->io_bytes[l];
if (dst->runtime[l] < src->runtime[l])
dst->runtime[l] = src->runtime[l];
} else {
- sum_stat(&dst->clat_stat[0], &src->clat_stat[l], first);
- sum_stat(&dst->slat_stat[0], &src->slat_stat[l], first);
- sum_stat(&dst->lat_stat[0], &src->lat_stat[l], first);
- sum_stat(&dst->bw_stat[0], &src->bw_stat[l], first);
- sum_stat(&dst->iops_stat[0], &src->iops_stat[l], first);
+ sum_stat(&dst->clat_stat[0], &src->clat_stat[l], first, false);
+ sum_stat(&dst->slat_stat[0], &src->slat_stat[l], first, false);
+ sum_stat(&dst->lat_stat[0], &src->lat_stat[l], first, false);
+ sum_stat(&dst->bw_stat[0], &src->bw_stat[l], first, true);
+ sum_stat(&dst->iops_stat[0], &src->iops_stat[l], first, true);
dst->io_bytes[0] += src->io_bytes[l];
}
}
- sum_stat(&dst->sync_stat, &src->sync_stat, first);
+ sum_stat(&dst->sync_stat, &src->sync_stat, first, false);
dst->usr_time += src->usr_time;
dst->sys_time += src->sys_time;
dst->ctx += src->ctx;
dst->io_u_submit[k] += src->io_u_submit[k];
dst->io_u_complete[k] += src->io_u_complete[k];
}
- for (k = 0; k < FIO_IO_U_LAT_N_NR; k++) {
+
+ for (k = 0; k < FIO_IO_U_LAT_N_NR; k++)
dst->io_u_lat_n[k] += src->io_u_lat_n[k];
+ for (k = 0; k < FIO_IO_U_LAT_U_NR; k++)
dst->io_u_lat_u[k] += src->io_u_lat_u[k];
+ for (k = 0; k < FIO_IO_U_LAT_M_NR; k++)
dst->io_u_lat_m[k] += src->io_u_lat_m[k];
- }
+
for (k = 0; k < FIO_IO_U_PLAT_NR; k++)
dst->io_u_sync_plat[k] += src->io_u_sync_plat[k];
dst->total_submit += src->total_submit;
dst->total_complete += src->total_complete;
dst->nr_zone_resets += src->nr_zone_resets;
+ dst->cachehit += src->cachehit;
+ dst->cachemiss += src->cachemiss;
}
void init_group_run_stat(struct group_run_stats *gs)
static inline void reset_io_stat(struct io_stat *ios)
{
- ios->max_val = ios->min_val = ios->samples = 0;
+ ios->min_val = -1ULL;
+ ios->max_val = ios->samples = 0;
ios->mean.u.f = ios->S.u.f = 0;
}
ts->total_submit = 0;
ts->total_complete = 0;
ts->nr_zone_resets = 0;
+ ts->cachehit = ts->cachemiss = 0;
}
static void __add_stat_to_log(struct io_log *iolog, enum fio_ddir ddir,