free(ovals);
}
-int calc_lat(struct io_stat *is, unsigned long *min, unsigned long *max,
- double *mean, double *dev)
+bool calc_lat(struct io_stat *is, unsigned long *min, unsigned long *max,
+ double *mean, double *dev)
{
double n = (double) is->samples;
if (n == 0)
- return 0;
+ return false;
*min = is->min_val;
*max = is->max_val;
else
*dev = 0;
- return 1;
+ return true;
}
void show_group_stats(struct group_run_stats *rs, struct buf_output *out)
const char *base = "(usec)";
char *minp, *maxp;
- if (!usec_to_msec(&min, &max, &mean, &dev))
+ if (usec_to_msec(&min, &max, &mean, &dev))
base = "(msec)";
minp = num2str(min, 6, 1, 0, 0);
if (!ddir_rw_sum(ts->io_bytes) && !ddir_rw_sum(ts->total_io_u))
return;
+
+ memset(time_buf, 0, sizeof(time_buf));
time(&time_p);
os_ctime_r((const time_t *) &time_p, time_buf, sizeof(time_buf));
log_buf(out, "\n");
}
-void json_add_job_opts(struct json_object *root, const char *name,
- struct flist_head *opt_list, bool num_jobs)
+static void json_add_job_opts(struct json_object *root, const char *name,
+ struct flist_head *opt_list, bool num_jobs)
{
struct json_object *dir_object;
struct flist_head *entry;
os_ctime_r((const time_t *) &now.tv_sec, time_buf,
sizeof(time_buf));
- time_buf[strlen(time_buf) - 1] = '\0';
+ if (time_buf[strlen(time_buf) - 1] == '\n')
+ time_buf[strlen(time_buf) - 1] = '\0';
root = json_create_object();
json_object_add_value_string(root, "fio version", fio_version_string);
{
regrow_log(td->slat_log);
regrow_log(td->clat_log);
+ regrow_log(td->clat_hist_log);
regrow_log(td->lat_log);
regrow_log(td->bw_log);
regrow_log(td->iops_log);
s = get_sample(iolog, cur_log, cur_log->nr_samples);
s->val = val;
- s->time = t;
+ s->time = t + (iolog->td ? iolog->td->unix_epoch : 0);
io_sample_set_ddir(iolog, s, ddir);
s->bs = bs;
void add_clat_sample(struct thread_data *td, enum fio_ddir ddir,
unsigned long usec, unsigned int bs, uint64_t offset)
{
+ unsigned long elapsed, this_window;
struct thread_stat *ts = &td->ts;
+ struct io_log *iolog = td->clat_hist_log;
td_io_u_lock(td);
if (ts->clat_percentiles)
add_clat_percentile_sample(ts, usec, ddir);
+ if (iolog && iolog->hist_msec) {
+ struct io_hist *hw = &iolog->hist_window[ddir];
+
+ hw->samples++;
+ elapsed = mtime_since_now(&td->epoch);
+ if (!hw->hist_last)
+ hw->hist_last = elapsed;
+ this_window = elapsed - hw->hist_last;
+
+ if (this_window >= iolog->hist_msec) {
+ unsigned int *io_u_plat;
+ struct io_u_plat_entry *dst;
+
+ /*
+ * Make a byte-for-byte copy of the latency histogram
+ * stored in td->ts.io_u_plat[ddir], recording it in a
+ * log sample. Note that the matching call to free() is
+ * located in iolog.c after printing this sample to the
+ * log file.
+ */
+ io_u_plat = (unsigned int *) td->ts.io_u_plat[ddir];
+ dst = malloc(sizeof(struct io_u_plat_entry));
+ memcpy(&(dst->io_u_plat), io_u_plat,
+ FIO_IO_U_PLAT_NR * sizeof(unsigned int));
+ flist_add(&dst->list, &hw->list);
+ __add_log_sample(iolog, (unsigned long)dst, ddir, bs,
+ elapsed, offset);
+
+ /*
+ * Update the last time we recorded as being now, minus
+ * any drift in time we encountered before actually
+ * making the record.
+ */
+ hw->hist_last = elapsed - (this_window - iolog->hist_msec);
+ hw->samples = 0;
+ }
+ }
+
td_io_u_unlock(td);
}
next = min(td->o.iops_avg_time, td->o.bw_avg_time);
continue;
}
- if (!per_unit_log(td->bw_log)) {
+ if (td->bw_log && !per_unit_log(td->bw_log)) {
tmp = add_bw_samples(td, &now);
if (tmp < next)
next = tmp;
}
- if (!per_unit_log(td->iops_log)) {
+ if (td->iops_log && !per_unit_log(td->iops_log)) {
tmp = add_iops_samples(td, &now);
if (tmp < next)
next = tmp;