We log submission and completion latencies, also log total latencies.
This makes it easier to graph and make histograms, if you care only
about the complete latency.
Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
filename. For this option, the postfix is _bw.log.
write_lat_log=str Same as write_bw_log, except that this option stores io
- completion latencies instead. If no filename is given
- with this option, the default filename of "jobname_type.log"
- is used. Even if the filename is given, fio will still
- append the type of log. So if one specifies
+ submission, completion, and total latencies instead. If no
+ filename is given with this option, the default filename of
+ "jobname_type.log" is used. Even if the filename is given,
+ fio will still append the type of log. So if one specifies
write_lat_log=foo
- The actual log names will be foo_clat.log and foo_slat.log.
- This helps fio_generate_plot fine the logs automatically.
+ The actual log names will be foo_slat.log, foo_slat.log,
+ and foo_lat.log. This helps fio_generate_plot fine the logs
+ automatically.
lockmem=int Pin down the specified amount of memory with mlock(2). Can
potentially be used instead of removing memory or booting
disk_util=bool Generate disk utilization statistics, if the platform
supports it. Defaults to on.
-disable_clat=bool Disable measurements of completion latency numbers. Useful
+disable_lat=bool Disable measurements of total latency numbers. Useful
only for cutting back the number of calls to gettimeofday,
as that does impact performance at really high IOPS rates.
Note that to really get rid of a large amount of these
calls, this option must be used with disable_slat and
disable_bw as well.
+disable_clat=bool Disable measurements of completion latency numbers. See
+ disable_lat.
+
disable_slat=bool Disable measurements of submission latency numbers. See
- disable_clat.
+ disable_slat.
disable_bw=bool Disable measurements of throughput/bandwidth numbers. See
- disable_clat.
+ disable_lat.
gtod_reduce=bool Enable all of the gettimeofday() reducing options
(disable_clat, disable_slat, disable_bw) plus reduce
filename is given with this option, the default filename of "jobname_type.log"
is used. Even if the filename is given, fio will still append the type of log.
.TP
-.B disable_clat \fR=\fPbool
-Disable measurements of completion latency numbers. Useful only for cutting
+.B disable_lat \fR=\fPbool
+Disable measurements of total latency numbers. Useful only for cutting
back the number of calls to gettimeofday, as that does impact performance at
really high IOPS rates. Note that to really get rid of a large amount of these
calls, this option must be used with disable_slat and disable_bw as well.
.TP
+.B disable_clat \fR=\fPbool
+Disable measurements of submission latency numbers. See \fBdisable_lat\fR.
+.TP
.B disable_slat \fR=\fPbool
-Disable measurements of submission latency numbers. See \fBdisable_clat\fR.
+Disable measurements of submission latency numbers. See \fBdisable_lat\fR.
.TP
.B disable_bw_measurement \fR=\fPbool
-Disable measurements of throughput/bandwidth numbers. See \fBdisable_clat\fR.
+Disable measurements of throughput/bandwidth numbers. See \fBdisable_lat\fR.
.TP
.BI lockmem \fR=\fPint
Pin the specified amount of memory with \fBmlock\fR\|(2). Can be used to
} else
finish_log(td, td->ts.bw_log, "bw");
}
+ if (td->ts.lat_log) {
+ if (td->o.lat_log_file) {
+ finish_log_named(td, td->ts.lat_log,
+ td->o.lat_log_file, "lat");
+ } else
+ finish_log(td, td->ts.lat_log, "lat");
+ }
if (td->ts.slat_log) {
if (td->o.lat_log_file) {
finish_log_named(td, td->ts.slat_log,
struct io_log *slat_log;
struct io_log *clat_log;
+ struct io_log *lat_log;
struct io_log *bw_log;
/*
*/
struct io_stat clat_stat[2]; /* completion latency */
struct io_stat slat_stat[2]; /* submission latency */
+ struct io_stat lat_stat[2]; /* total latency */
struct io_stat bw_stat[2]; /* bandwidth stats */
unsigned long long stat_io_bytes[2];
unsigned int zero_buffers;
unsigned int refill_buffers;
unsigned int time_based;
+ unsigned int disable_lat;
unsigned int disable_clat;
unsigned int disable_slat;
unsigned int disable_bw;
echo Making clat logs $PLOT_LINE
echo "set title 'Completion latency - $TITLE'; set xlabel 'time (msec)'; set ylabel 'latency (msec)'; set terminal png; set output '$TITLE-clat.png'; plot " $PLOT_LINE | $GNUPLOT -
fi
+
+PLOT_LINE=""
+for i in *_lat.log; do
+ if [ ! -r $i ]; then
+ continue
+ fi
+ PT=$(echo $i | sed s/_lat.log//g)
+ if [ "$PLOT_LINE"x != "x" ]; then
+ PLOT_LINE=$PLOT_LINE", "
+ fi
+
+ PLOT_LINE=$PLOT_LINE"'$i' title '$PT' with lines"
+done
+
+if [ "$PLOT_LINE"x != "x" ]; then
+ echo Making lat logs $PLOT_LINE
+ echo "set title 'Latency - $TITLE'; set xlabel 'time (msec)'; set ylabel 'latency (msec)'; set terminal png; set output '$TITLE-lat.png'; plot " $PLOT_LINE | $GNUPLOT -
+fi
td->ts.clat_stat[0].min_val = td->ts.clat_stat[1].min_val = ULONG_MAX;
td->ts.slat_stat[0].min_val = td->ts.slat_stat[1].min_val = ULONG_MAX;
+ td->ts.lat_stat[0].min_val = td->ts.lat_stat[1].min_val = ULONG_MAX;
td->ts.bw_stat[0].min_val = td->ts.bw_stat[1].min_val = ULONG_MAX;
td->ddir_nr = td->o.ddir_nr;
goto err;
if (td->o.write_lat_log) {
+ setup_log(&td->ts.lat_log);
setup_log(&td->ts.slat_log);
setup_log(&td->ts.clat_log);
}
if (!td->o.disable_clat || !td->o.disable_bw)
lusec = utime_since(&io_u->issue_time,
&icd->time);
+ if (!td->o.disable_lat) {
+ unsigned long tusec;
+ tusec = utime_since(&io_u->start_time,
+ &icd->time);
+ add_lat_sample(td, idx, tusec, bytes);
+ }
if (!td->o.disable_clat) {
add_clat_sample(td, idx, lusec, bytes);
io_u_mark_latency(td, lusec);
/*
* Logging
*/
+extern void add_lat_sample(struct thread_data *, enum fio_ddir, unsigned long,
+ unsigned int);
extern void add_clat_sample(struct thread_data *, enum fio_ddir, unsigned long,
unsigned int);
extern void add_slat_sample(struct thread_data *, enum fio_ddir, unsigned long,
struct thread_data *td = data;
int val = *il;
+ td->o.disable_lat = !!val;
td->o.disable_clat = !!val;
td->o.disable_slat = !!val;
td->o.disable_bw = !!val;
.cb = str_gtod_reduce_cb,
.def = "0",
},
+ {
+ .name = "disable_lat",
+ .type = FIO_OPT_BOOL,
+ .off1 = td_var_offset(disable_lat),
+ .help = "Disable latency numbers",
+ .parent = "gtod_reduce",
+ .def = "0",
+ },
{
.name = "disable_clat",
.type = FIO_OPT_BOOL,
free(minp);
free(maxp);
}
+ if (calc_lat(&ts->lat_stat[ddir], &min, &max, &mean, &dev)) {
+ const char *base = "(usec)";
+ char *minp, *maxp;
+
+ if (!usec_to_msec(&min, &max, &mean, &dev))
+ base = "(msec)";
+
+ minp = num2str(min, 6, 1, 0);
+ maxp = num2str(max, 6, 1, 0);
+
+ log_info(" lat %s: min=%s, max=%s, avg=%5.02f,"
+ " stdev=%5.02f\n", base, minp, maxp, mean, dev);
+
+ free(minp);
+ free(maxp);
+ }
if (calc_lat(&ts->bw_stat[ddir], &min, &max, &mean, &dev)) {
double p_of_agg;
else
log_info(";%lu;%lu;%f;%f", 0UL, 0UL, 0.0, 0.0);
+ if (calc_lat(&ts->lat_stat[ddir], &min, &max, &mean, &dev))
+ log_info(";%lu;%lu;%f;%f", min, max, mean, dev);
+ else
+ log_info(";%lu;%lu;%f;%f", 0UL, 0UL, 0.0, 0.0);
+
if (calc_lat(&ts->bw_stat[ddir], &min, &max, &mean, &dev)) {
double p_of_agg;
memset(ts, 0, sizeof(*ts));
for (j = 0; j <= DDIR_WRITE; 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;
for (l = 0; l <= DDIR_WRITE; l++) {
sum_stat(&ts->clat_stat[l], &td->ts.clat_stat[l], idx);
sum_stat(&ts->slat_stat[l], &td->ts.slat_stat[l], idx);
+ sum_stat(&ts->lat_stat[l], &td->ts.lat_stat[l], idx);
sum_stat(&ts->bw_stat[l], &td->ts.bw_stat[l], idx);
ts->stat_io_bytes[l] += td->ts.stat_io_bytes[l];
add_log_sample(td, ts->slat_log, usec, ddir, bs);
}
+void add_lat_sample(struct thread_data *td, enum fio_ddir ddir,
+ unsigned long usec, unsigned int bs)
+{
+ struct thread_stat *ts = &td->ts;
+
+ add_stat_sample(&ts->lat_stat[ddir], usec);
+
+ if (ts->lat_log)
+ add_log_sample(td, ts->lat_log, usec, ddir, bs);
+}
+
void add_bw_sample(struct thread_data *td, enum fio_ddir ddir, unsigned int bs,
struct timeval *t)
{