stat: add comments describing the quirky behavior of clat prio samples
[fio.git] / stat.c
diff --git a/stat.c b/stat.c
index 99275620b69d7d5fcac471fbe0426b65d96534c2..8bb49e4be9181918870752bdd40eb5591b21e63e 100644 (file)
--- a/stat.c
+++ b/stat.c
 #include "zbd.h"
 #include "oslib/asprintf.h"
 
+#ifdef WIN32
+#define LOG_MSEC_SLACK 2
+#else
 #define LOG_MSEC_SLACK 1
+#endif
 
 struct fio_sem *stat_sem;
 
@@ -211,7 +215,7 @@ static void show_clat_percentiles(uint64_t *io_u_plat, unsigned long long nr,
 
        len = calc_clat_percentiles(io_u_plat, nr, plist, &ovals, &maxv, &minv);
        if (!len || !ovals)
-               goto out;
+               return;
 
        /*
         * We default to nsecs, but if the value range is such that we
@@ -258,7 +262,6 @@ static void show_clat_percentiles(uint64_t *io_u_plat, unsigned long long nr,
                        log_buf(out, "\n");
        }
 
-out:
        free(ovals);
 }
 
@@ -480,22 +483,13 @@ static void show_mixed_ddir_status(struct group_run_stats *rs, struct thread_sta
        struct thread_stat *ts_lcl;
 
        int i2p;
-       int ddir = 0, i;
+       int ddir = 0;
 
        /* Handle aggregation of Reads (ddir = 0), Writes (ddir = 1), and Trims (ddir = 2) */
        ts_lcl = malloc(sizeof(struct thread_stat));
        memset((void *)ts_lcl, 0, sizeof(struct thread_stat));
        ts_lcl->unified_rw_rep = UNIFIED_MIXED;               /* calculate mixed stats  */
-       for (i = 0; i < DDIR_RWDIR_CNT; i++) {
-               ts_lcl->clat_stat[i].min_val = ULONG_MAX;
-               ts_lcl->slat_stat[i].min_val = ULONG_MAX;
-               ts_lcl->lat_stat[i].min_val = ULONG_MAX;
-               ts_lcl->bw_stat[i].min_val = ULONG_MAX;
-               ts_lcl->iops_stat[i].min_val = ULONG_MAX;
-               ts_lcl->clat_high_prio_stat[i].min_val = ULONG_MAX;
-               ts_lcl->clat_low_prio_stat[i].min_val = ULONG_MAX;
-       }
-       ts_lcl->sync_stat.min_val = ULONG_MAX;
+       init_thread_stat_min_vals(ts_lcl);
 
        sum_thread_stats(ts_lcl, ts, 1);
 
@@ -1463,22 +1457,12 @@ static void show_mixed_ddir_status_terse(struct thread_stat *ts,
                                   int ver, struct buf_output *out)
 {
        struct thread_stat *ts_lcl;
-       int i;
 
        /* Handle aggregation of Reads (ddir = 0), Writes (ddir = 1), and Trims (ddir = 2) */
        ts_lcl = malloc(sizeof(struct thread_stat));
        memset((void *)ts_lcl, 0, sizeof(struct thread_stat));
        ts_lcl->unified_rw_rep = UNIFIED_MIXED;               /* calculate mixed stats  */
-       for (i = 0; i < DDIR_RWDIR_CNT; i++) {
-               ts_lcl->clat_stat[i].min_val = ULONG_MAX;
-               ts_lcl->slat_stat[i].min_val = ULONG_MAX;
-               ts_lcl->lat_stat[i].min_val = ULONG_MAX;
-               ts_lcl->bw_stat[i].min_val = ULONG_MAX;
-               ts_lcl->iops_stat[i].min_val = ULONG_MAX;
-               ts_lcl->clat_high_prio_stat[i].min_val = ULONG_MAX;
-               ts_lcl->clat_low_prio_stat[i].min_val = ULONG_MAX;
-       }
-       ts_lcl->sync_stat.min_val = ULONG_MAX;
+       init_thread_stat_min_vals(ts_lcl);
        ts_lcl->lat_percentiles = ts->lat_percentiles;
        ts_lcl->clat_percentiles = ts->clat_percentiles;
        ts_lcl->slat_percentiles = ts->slat_percentiles;
@@ -1665,22 +1649,12 @@ static void add_mixed_ddir_status_json(struct thread_stat *ts,
                struct group_run_stats *rs, struct json_object *parent)
 {
        struct thread_stat *ts_lcl;
-       int i;
 
        /* Handle aggregation of Reads (ddir = 0), Writes (ddir = 1), and Trims (ddir = 2) */
        ts_lcl = malloc(sizeof(struct thread_stat));
        memset((void *)ts_lcl, 0, sizeof(struct thread_stat));
        ts_lcl->unified_rw_rep = UNIFIED_MIXED;               /* calculate mixed stats  */
-       for (i = 0; i < DDIR_RWDIR_CNT; i++) {
-               ts_lcl->clat_stat[i].min_val = ULONG_MAX;
-               ts_lcl->slat_stat[i].min_val = ULONG_MAX;
-               ts_lcl->lat_stat[i].min_val = ULONG_MAX;
-               ts_lcl->bw_stat[i].min_val = ULONG_MAX;
-               ts_lcl->iops_stat[i].min_val = ULONG_MAX;
-               ts_lcl->clat_high_prio_stat[i].min_val = ULONG_MAX;
-               ts_lcl->clat_low_prio_stat[i].min_val = ULONG_MAX;
-       }
-       ts_lcl->sync_stat.min_val = ULONG_MAX;
+       init_thread_stat_min_vals(ts_lcl);
        ts_lcl->lat_percentiles = ts->lat_percentiles;
        ts_lcl->clat_percentiles = ts->clat_percentiles;
        ts_lcl->slat_percentiles = ts->slat_percentiles;
@@ -2267,22 +2241,27 @@ void init_group_run_stat(struct group_run_stats *gs)
                gs->min_bw[i] = gs->min_run[i] = ~0UL;
 }
 
-void init_thread_stat(struct thread_stat *ts)
+void init_thread_stat_min_vals(struct thread_stat *ts)
 {
-       int j;
+       int i;
 
+       for (i = 0; i < DDIR_RWDIR_CNT; i++) {
+               ts->clat_stat[i].min_val = ULONG_MAX;
+               ts->slat_stat[i].min_val = ULONG_MAX;
+               ts->lat_stat[i].min_val = ULONG_MAX;
+               ts->bw_stat[i].min_val = ULONG_MAX;
+               ts->iops_stat[i].min_val = ULONG_MAX;
+               ts->clat_high_prio_stat[i].min_val = ULONG_MAX;
+               ts->clat_low_prio_stat[i].min_val = ULONG_MAX;
+       }
+       ts->sync_stat.min_val = ULONG_MAX;
+}
+
+void init_thread_stat(struct thread_stat *ts)
+{
        memset(ts, 0, sizeof(*ts));
 
-       for (j = 0; j < DDIR_RWDIR_CNT; j++) {
-               ts->lat_stat[j].min_val = -1UL;
-               ts->clat_stat[j].min_val = -1UL;
-               ts->slat_stat[j].min_val = -1UL;
-               ts->bw_stat[j].min_val = -1UL;
-               ts->iops_stat[j].min_val = -1UL;
-               ts->clat_high_prio_stat[j].min_val = -1UL;
-               ts->clat_low_prio_stat[j].min_val = -1UL;
-       }
-       ts->sync_stat.min_val = -1UL;
+       init_thread_stat_min_vals(ts);
        ts->groupid = -1;
 }
 
@@ -2709,27 +2688,25 @@ static inline void add_stat_sample(struct io_stat *is, unsigned long long data)
  */
 static struct io_logs *get_new_log(struct io_log *iolog)
 {
-       size_t new_size, new_samples;
+       size_t new_samples;
        struct io_logs *cur_log;
 
        /*
         * Cap the size at MAX_LOG_ENTRIES, so we don't keep doubling
         * forever
         */
-       if (!iolog->cur_log_max)
-               new_samples = DEF_LOG_ENTRIES;
-       else {
+       if (!iolog->cur_log_max) {
+               new_samples = iolog->td->o.log_entries;
+       else {
                new_samples = iolog->cur_log_max * 2;
                if (new_samples > MAX_LOG_ENTRIES)
                        new_samples = MAX_LOG_ENTRIES;
        }
 
-       new_size = new_samples * log_entry_sz(iolog);
-
        cur_log = smalloc(sizeof(*cur_log));
        if (cur_log) {
                INIT_FLIST_HEAD(&cur_log->list);
-               cur_log->log = malloc(new_size);
+               cur_log->log = calloc(new_samples, log_entry_sz(iolog));
                if (cur_log->log) {
                        cur_log->nr_samples = 0;
                        cur_log->max_samples = new_samples;
@@ -3112,6 +3089,15 @@ void add_clat_sample(struct thread_data *td, enum fio_ddir ddir,
 
        add_stat_sample(&ts->clat_stat[ddir], nsec);
 
+       /*
+        * When lat_percentiles=1 (default 0), the reported high/low priority
+        * percentiles and stats are used for describing total latency values,
+        * even though the variable names themselves start with clat_.
+        *
+        * Because of the above definition, add a prio stat sample only when
+        * lat_percentiles=0. add_lat_sample() will add the prio stat sample
+        * when lat_percentiles=1.
+        */
        if (!ts->lat_percentiles) {
                if (high_prio)
                        add_stat_sample(&ts->clat_high_prio_stat[ddir], nsec);
@@ -3124,6 +3110,11 @@ void add_clat_sample(struct thread_data *td, enum fio_ddir ddir,
                               offset, ioprio);
 
        if (ts->clat_percentiles) {
+               /*
+                * Because of the above definition, add a prio lat percentile
+                * sample only when lat_percentiles=0. add_lat_sample() will add
+                * the prio lat percentile sample when lat_percentiles=1.
+                */
                if (ts->lat_percentiles)
                        add_lat_percentile_sample_noprio(ts, nsec, ddir, FIO_CLAT);
                else
@@ -3217,6 +3208,16 @@ void add_lat_sample(struct thread_data *td, enum fio_ddir ddir,
                add_log_sample(td, td->lat_log, sample_val(nsec), ddir, bs,
                               offset, ioprio);
 
+       /*
+        * When lat_percentiles=1 (default 0), the reported high/low priority
+        * percentiles and stats are used for describing total latency values,
+        * even though the variable names themselves start with clat_.
+        *
+        * Because of the above definition, add a prio stat and prio lat
+        * percentile sample only when lat_percentiles=1. add_clat_sample() will
+        * add the prio stat and prio lat percentile sample when
+        * lat_percentiles=0.
+        */
        if (ts->lat_percentiles) {
                add_lat_percentile_sample(ts, nsec, ddir, high_prio, FIO_LAT);
                if (high_prio)