stat: disable per prio stats where not needed
authorNiklas Cassel <niklas.cassel@wdc.com>
Thu, 3 Feb 2022 19:28:30 +0000 (19:28 +0000)
committerJens Axboe <axboe@kernel.dk>
Thu, 3 Feb 2022 22:30:06 +0000 (15:30 -0700)
In order to avoid allocating a clat_prio_stat array for threadstats that we
know will never be able to contain more than a single priority, introduce a
new member disable_prio_stat in struct thread_stat.

The naming prefix is disable, since we want the default value to be 0
(enabled). This is because in default case, we do want sum_thread_stats()
to generate a per prio stat array. Only in the case where we know that we
don't want per priority stats to be generated, should this member be set
to 1.

Server version is intentionally not incremented, as it will be incremented
in a later patch in the series. No need to bump it multiple times for the
same patch series.

Signed-off-by: Niklas Cassel <niklas.cassel@wdc.com>
Reviewed-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
Link: https://lore.kernel.org/r/20220203192814.18552-14-Niklas.Cassel@wdc.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
client.c
rate-submit.c
server.c
stat.c
stat.h

index cf082c74e689500d4829544133407bc50e76b1ac..d7a80f0285128ff4054893b751edf67e26b1ed22 100644 (file)
--- a/client.c
+++ b/client.c
@@ -955,6 +955,7 @@ static void convert_ts(struct thread_stat *dst, struct thread_stat *src)
        dst->members            = le32_to_cpu(src->members);
        dst->unified_rw_rep     = le32_to_cpu(src->unified_rw_rep);
        dst->ioprio             = le32_to_cpu(src->ioprio);
+       dst->disable_prio_stat  = le32_to_cpu(src->disable_prio_stat);
 
        for (i = 0; i < DDIR_RWDIR_CNT; i++) {
                convert_io_stat(&dst->clat_stat[i], &src->clat_stat[i]);
index 752c30a5f171d6f0e541ef79ce9fc5c341195d58..e3a71168013f6526190b75323b6cd06160488a57 100644 (file)
@@ -195,6 +195,15 @@ static void io_workqueue_exit_worker_fn(struct submit_worker *sw,
        struct thread_data *td = sw->priv;
 
        (*sum_cnt)++;
+
+       /*
+        * io_workqueue_update_acct_fn() doesn't support per prio stats, and
+        * even if it did, offload can't be used with all async IO engines.
+        * If group reporting is set in the parent td, the group result
+        * generated by __show_run_stats() can still contain multiple prios
+        * from different offloaded jobs.
+        */
+       sw->wq->td->ts.disable_prio_stat = 1;
        sum_thread_stats(&sw->wq->td->ts, &td->ts);
 
        fio_options_free(td);
index 05b65631fb9051952b7fa13a5ecb87406ee649ff..6b45ff2ee178ab65fef7aa264f1dd89404cab00b 100644 (file)
--- a/server.c
+++ b/server.c
@@ -1706,6 +1706,7 @@ void fio_server_send_ts(struct thread_stat *ts, struct group_run_stats *rs)
        p.ts.members            = cpu_to_le32(ts->members);
        p.ts.unified_rw_rep     = cpu_to_le32(ts->unified_rw_rep);
        p.ts.ioprio             = cpu_to_le32(ts->ioprio);
+       p.ts.disable_prio_stat  = cpu_to_le32(ts->disable_prio_stat);
 
        for (i = 0; i < DDIR_RWDIR_CNT; i++) {
                convert_io_stat(&p.ts.clat_stat[i], &ts->clat_stat[i]);
diff --git a/stat.c b/stat.c
index baaa29f2d1603602342711205797f24c877d13aa..f783aed851e263a57a4452852d4075d5fc54b91c 100644 (file)
--- a/stat.c
+++ b/stat.c
@@ -2171,6 +2171,58 @@ void init_thread_stat(struct thread_stat *ts)
        ts->groupid = -1;
 }
 
+static void init_per_prio_stats(struct thread_stat *threadstats, int nr_ts)
+{
+       struct thread_data *td;
+       struct thread_stat *ts;
+       int i, j, last_ts, idx;
+       enum fio_ddir ddir;
+
+       j = 0;
+       last_ts = -1;
+       idx = 0;
+
+       /*
+        * Loop through all tds, if a td requires per prio stats, temporarily
+        * store a 1 in ts->disable_prio_stat, and then do an additional
+        * loop at the end where we invert the ts->disable_prio_stat values.
+        */
+       for_each_td(td, i) {
+               if (!td->o.stats)
+                       continue;
+               if (idx &&
+                   (!td->o.group_reporting ||
+                    (td->o.group_reporting && last_ts != td->groupid))) {
+                       idx = 0;
+                       j++;
+               }
+
+               last_ts = td->groupid;
+               ts = &threadstats[j];
+
+               /* idx == 0 means first td in group, or td is not in a group. */
+               if (idx == 0)
+                       ts->ioprio = td->ioprio;
+               else if (td->ioprio != ts->ioprio)
+                       ts->disable_prio_stat = 1;
+
+               for (ddir = 0; ddir < DDIR_RWDIR_CNT; ddir++) {
+                       if (td->ts.clat_prio[ddir]) {
+                               ts->disable_prio_stat = 1;
+                               break;
+                       }
+               }
+
+               idx++;
+       }
+
+       /* Loop through all dst threadstats and fixup the values. */
+       for (i = 0; i < nr_ts; i++) {
+               ts = &threadstats[i];
+               ts->disable_prio_stat = !ts->disable_prio_stat;
+       }
+}
+
 void __show_run_stats(void)
 {
        struct group_run_stats *runstats, *rs;
@@ -2217,6 +2269,8 @@ void __show_run_stats(void)
                opt_lists[i] = NULL;
        }
 
+       init_per_prio_stats(threadstats, nr_ts);
+
        j = 0;
        last_ts = -1;
        idx = 0;
diff --git a/stat.h b/stat.h
index 188c57f3f827b4657c8a07cde9595000db2de557..6c86fa22b9b760f3c0a4842edf86a362f99fbc07 100644 (file)
--- a/stat.h
+++ b/stat.h
@@ -174,6 +174,7 @@ struct thread_stat {
        char description[FIO_JOBDESC_SIZE];
        uint32_t members;
        uint32_t unified_rw_rep;
+       uint32_t disable_prio_stat;
 
        /*
         * bandwidth and latency stats