const char *filename)
{
struct io_log *l;
+ int i;
+ struct io_u_plat_entry *entry;
+ struct flist_head *list;
l = scalloc(1, sizeof(*l));
INIT_FLIST_HEAD(&l->io_logs);
l->filename = strdup(filename);
l->td = p->td;
+ /* Initialize histogram lists for each r/w direction,
+ * with initial io_u_plat of all zeros:
+ */
+ for (i = 0; i < DDIR_RWDIR_CNT; i++) {
+ list = &l->hist_window[i].list.list;
+ INIT_FLIST_HEAD(list);
+ entry = calloc(1, sizeof(struct io_u_plat_entry));
+ flist_add(&entry->list, list);
+ }
+
if (l->td && l->td->o.io_submit_mode != IO_MODE_OFFLOAD) {
struct io_logs *p;
sfree(log);
}
- static inline unsigned long hist_sum(int j, int stride, unsigned int *io_u_plat)
+ static inline unsigned long hist_sum(int j, int stride, unsigned int *io_u_plat,
+ unsigned int *io_u_plat_last)
{
unsigned long sum;
int k;
for (k = sum = 0; k < stride; k++)
- sum += io_u_plat[j + k];
+ sum += io_u_plat[j + k] - io_u_plat_last[j + k];
return sum;
}
-void flush_hist_samples(FILE *f, int hist_coarseness, void *samples,
- uint64_t sample_size)
+static void flush_hist_samples(FILE *f, int hist_coarseness, void *samples,
+ uint64_t sample_size)
{
struct io_sample *s;
int log_offset;
uint64_t i, j, nr_samples;
+ struct io_u_plat_entry *entry, *entry_before;
unsigned int *io_u_plat;
+ unsigned int *io_u_plat_before;
int stride = 1 << hist_coarseness;
for (i = 0; i < nr_samples; i++) {
s = __get_sample(samples, log_offset, i);
- io_u_plat = (unsigned int *) (uintptr_t) s->val;
+
+ entry = (struct io_u_plat_entry *) s->val;
+ io_u_plat = entry->io_u_plat;
+
+ entry_before = flist_first_entry(&entry->list, struct io_u_plat_entry, list);
+ io_u_plat_before = entry_before->io_u_plat;
+
fprintf(f, "%lu, %u, %u, ", (unsigned long)s->time,
io_sample_ddir(s), s->bs);
for (j = 0; j < FIO_IO_U_PLAT_NR - stride; j += stride) {
- fprintf(f, "%lu, ", hist_sum(j, stride, io_u_plat));
+ fprintf(f, "%lu, ", hist_sum(j, stride, io_u_plat, io_u_plat_before));
}
fprintf(f, "%lu\n", (unsigned long)
- hist_sum(FIO_IO_U_PLAT_NR - stride, stride, io_u_plat));
- free(io_u_plat);
+ hist_sum(FIO_IO_U_PLAT_NR - stride, stride, io_u_plat,
+ io_u_plat_before));
+
+ flist_del(&entry_before->list);
+ free(entry_before);
}
}
fio_fp64_t S;
};
+ struct io_u_plat_list {
+ struct flist_head list;
+ };
+
struct io_hist {
uint64_t samples;
unsigned long hist_last;
+ struct io_u_plat_list list;
};
/*
unsigned long avg_msec;
unsigned long avg_last;
- /*
- * Windowed latency histograms, for keeping track of when we need to
- * save a copy of the histogram every approximately hist_msec milliseconds.
- */
+ /*
+ * Windowed latency histograms, for keeping track of when we need to
+ * save a copy of the histogram every approximately hist_msec
+ * milliseconds.
+ */
struct io_hist hist_window[DDIR_RWDIR_CNT];
unsigned long hist_msec;
int hist_coarseness;
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);
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;
if (this_window >= iolog->hist_msec) {
unsigned int *io_u_plat;
- unsigned int *dst;
+ struct io_u_plat_entry *dst;
/*
* Make a byte-for-byte copy of the latency histogram
* log file.
*/
io_u_plat = (unsigned int *) td->ts.io_u_plat[ddir];
- dst = malloc(FIO_IO_U_PLAT_NR * sizeof(unsigned int));
- memcpy(dst, io_u_plat,
+ dst = malloc(sizeof(struct io_u_plat_entry));
+ memcpy(&(dst->io_u_plat), io_u_plat,
FIO_IO_U_PLAT_NR * sizeof(unsigned int));
- __add_log_sample(iolog, (unsigned long )dst, ddir, bs,
+ flist_add(&dst->list, &hw->list.list);
+ __add_log_sample(iolog, (unsigned long)dst, ddir, bs,
elapsed, offset);
/*
uint8_t run_str[];
} __attribute__((packed));
+ struct io_u_plat_entry {
+ struct flist_head list;
+ unsigned int io_u_plat[FIO_IO_U_PLAT_NR];
+ };
+
extern struct fio_mutex *stat_mutex;
extern struct jobs_eta *get_jobs_eta(bool force, size_t *size);
extern struct json_object * show_thread_status(struct thread_stat *ts, struct group_run_stats *rs, struct flist_head *, struct buf_output *);
extern void show_group_stats(struct group_run_stats *rs, struct buf_output *);
-extern int calc_thread_status(struct jobs_eta *je, int force);
+extern bool calc_thread_status(struct jobs_eta *je, int force);
extern void display_thread_status(struct jobs_eta *je);
extern void show_run_stats(void);
extern void __show_run_stats(void);
extern void init_thread_stat(struct thread_stat *ts);
extern void init_group_run_stat(struct group_run_stats *gs);
extern void eta_to_str(char *str, unsigned long eta_sec);
-extern int calc_lat(struct io_stat *is, unsigned long *min, unsigned long *max, double *mean, double *dev);
+extern bool calc_lat(struct io_stat *is, unsigned long *min, unsigned long *max, double *mean, double *dev);
extern unsigned int calc_clat_percentiles(unsigned int *io_u_plat, unsigned long nr, fio_fp64_t *plist, unsigned int **output, unsigned int *maxv, unsigned int *minv);
extern void stat_calc_lat_m(struct thread_stat *ts, double *io_u_lat);
extern void stat_calc_lat_u(struct thread_stat *ts, double *io_u_lat);
extern struct io_log *agg_io_log[DDIR_RWDIR_CNT];
extern int write_bw_log;
-static inline int usec_to_msec(unsigned long *min, unsigned long *max,
- double *mean, double *dev)
+static inline bool usec_to_msec(unsigned long *min, unsigned long *max,
+ double *mean, double *dev)
{
if (*min > 1000 && *max > 1000 && *mean > 1000.0 && *dev > 1000.0) {
*min /= 1000;
*max /= 1000;
*mean /= 1000.0;
*dev /= 1000.0;
- return 0;
+ return true;
}
- return 1;
+ return false;
}
/*
* Worst level condensing would be 1:5, so allow enough room for that