Optimize the code that copies strings
[fio.git] / eta.c
diff --git a/eta.c b/eta.c
index 9111f5ec1e670bfc4177c12e24601795be291efb..647a1bdd8eed7433c2413fde356844720b45e722 100644 (file)
--- a/eta.c
+++ b/eta.c
@@ -177,12 +177,27 @@ static unsigned long thread_eta(struct thread_data *td)
                bytes_total = td->fill_device_size;
        }
 
-       if (td->o.zone_size && td->o.zone_skip && bytes_total) {
+       /*
+        * If io_size is set, bytes_total is an exact value that does not need
+        * adjustment.
+        */
+       if (td->o.zone_size && td->o.zone_skip && bytes_total &&
+           !fio_option_is_set(&td->o, io_size)) {
                unsigned int nr_zones;
                uint64_t zone_bytes;
 
-               zone_bytes = bytes_total + td->o.zone_size + td->o.zone_skip;
-               nr_zones = (zone_bytes - 1) / (td->o.zone_size + td->o.zone_skip);
+               /*
+                * Calculate the upper bound of the number of zones that will
+                * be processed, including skipped bytes between zones. If this
+                * is larger than total_io_size (e.g. when --io_size or --size
+                * specify a small value), use the lower bound to avoid
+                * adjustments to a negative value that would result in a very
+                * large bytes_total and an incorrect eta.
+                */
+               zone_bytes = td->o.zone_size + td->o.zone_skip;
+               nr_zones = (bytes_total + zone_bytes - 1) / zone_bytes;
+               if (bytes_total < nr_zones * td->o.zone_skip)
+                       nr_zones = bytes_total / zone_bytes;
                bytes_total -= nr_zones * td->o.zone_skip;
        }
 
@@ -377,6 +392,9 @@ bool calc_thread_status(struct jobs_eta *je, int force)
        static unsigned long long disp_io_iops[DDIR_RWDIR_CNT];
        static struct timespec rate_prev_time, disp_prev_time;
 
+       void *je_rate = (void *) je->rate;
+       void *je_iops = (void *) je->iops;
+
        if (!force) {
                if (!(output_format & FIO_OUTPUT_NORMAL) &&
                    f_out == stdout)
@@ -492,7 +510,7 @@ bool calc_thread_status(struct jobs_eta *je, int force)
 
        if (write_bw_log && rate_time > bw_avg_time && !in_ramp_time(td)) {
                calc_rate(unified_rw_rep, rate_time, io_bytes, rate_io_bytes,
-                               je->rate);
+                               je_rate);
                memcpy(&rate_prev_time, &now, sizeof(now));
                add_agg_sample(sample_val(je->rate[DDIR_READ]), DDIR_READ, 0);
                add_agg_sample(sample_val(je->rate[DDIR_WRITE]), DDIR_WRITE, 0);
@@ -504,8 +522,8 @@ bool calc_thread_status(struct jobs_eta *je, int force)
        if (!force && !eta_time_within_slack(disp_time))
                return false;
 
-       calc_rate(unified_rw_rep, disp_time, io_bytes, disp_io_bytes, je->rate);
-       calc_iops(unified_rw_rep, disp_time, io_iops, disp_io_iops, je->iops);
+       calc_rate(unified_rw_rep, disp_time, io_bytes, disp_io_bytes, je_rate);
+       calc_iops(unified_rw_rep, disp_time, io_iops, disp_io_iops, je_iops);
 
        memcpy(&disp_prev_time, &now, sizeof(now));
 
@@ -518,6 +536,63 @@ bool calc_thread_status(struct jobs_eta *je, int force)
        return true;
 }
 
+static int gen_eta_str(struct jobs_eta *je, char *p, size_t left,
+                      char **rate_str, char **iops_str)
+{
+       bool has_r = je->rate[DDIR_READ] || je->iops[DDIR_READ];
+       bool has_w = je->rate[DDIR_WRITE] || je->iops[DDIR_WRITE];
+       bool has_t = je->rate[DDIR_TRIM] || je->iops[DDIR_TRIM];
+       int l = 0;
+
+       if (!has_r && !has_w && !has_t)
+               return 0;
+
+       if (has_r) {
+               l += snprintf(p + l, left - l, "[r=%s", rate_str[DDIR_READ]);
+               if (!has_w)
+                       l += snprintf(p + l, left - l, "]");
+       }
+       if (has_w) {
+               if (has_r)
+                       l += snprintf(p + l, left - l, ",");
+               else
+                       l += snprintf(p + l, left - l, "[");
+               l += snprintf(p + l, left - l, "w=%s", rate_str[DDIR_WRITE]);
+               if (!has_t)
+                       l += snprintf(p + l, left - l, "]");
+       }
+       if (has_t) {
+               if (has_r || has_w)
+                       l += snprintf(p + l, left - l, ",");
+               else if (!has_r && !has_w)
+                       l += snprintf(p + l, left - l, "[");
+               l += snprintf(p + l, left - l, "t=%s]", rate_str[DDIR_TRIM]);
+       }
+       if (has_r) {
+               l += snprintf(p + l, left - l, "[r=%s", iops_str[DDIR_READ]);
+               if (!has_w)
+                       l += snprintf(p + l, left - l, " IOPS]");
+       }
+       if (has_w) {
+               if (has_r)
+                       l += snprintf(p + l, left - l, ",");
+               else
+                       l += snprintf(p + l, left - l, "[");
+               l += snprintf(p + l, left - l, "w=%s", iops_str[DDIR_WRITE]);
+               if (!has_t)
+                       l += snprintf(p + l, left - l, " IOPS]");
+       }
+       if (has_t) {
+               if (has_r || has_w)
+                       l += snprintf(p + l, left - l, ",");
+               else if (!has_r && !has_w)
+                       l += snprintf(p + l, left - l, "[");
+               l += snprintf(p + l, left - l, "t=%s IOPS]", iops_str[DDIR_TRIM]);
+       }
+
+       return l;
+}
+
 void display_thread_status(struct jobs_eta *je)
 {
        static struct timespec disp_eta_new_line;
@@ -592,21 +667,10 @@ void display_thread_status(struct jobs_eta *je)
                }
 
                left = sizeof(output) - (p - output) - 1;
+               l = snprintf(p, left, ": [%s][%s]", je->run_str, perc_str);
+               l += gen_eta_str(je, p + l, left - l, rate_str, iops_str);
+               l += snprintf(p + l, left - l, "[eta %s]", eta_str);
 
-               if (je->rate[DDIR_TRIM] || je->iops[DDIR_TRIM])
-                       l = snprintf(p, left,
-                               ": [%s][%s][r=%s,w=%s,t=%s][r=%s,w=%s,t=%s IOPS][eta %s]",
-                               je->run_str, perc_str, rate_str[DDIR_READ],
-                               rate_str[DDIR_WRITE], rate_str[DDIR_TRIM],
-                               iops_str[DDIR_READ], iops_str[DDIR_WRITE],
-                               iops_str[DDIR_TRIM], eta_str);
-               else
-                       l = snprintf(p, left,
-                               ": [%s][%s][r=%s,w=%s][r=%s,w=%s IOPS][eta %s]",
-                               je->run_str, perc_str,
-                               rate_str[DDIR_READ], rate_str[DDIR_WRITE],
-                               iops_str[DDIR_READ], iops_str[DDIR_WRITE],
-                               eta_str);
                /* If truncation occurred adjust l so p is on the null */
                if (l >= left)
                        l = left - 1;