(https://en.wikipedia.org/wiki/Poisson_point_process). The lambda will be
10^6 / IOPS for the given workload.
+.. option:: rate_ignore_thinktime=bool
+
+ By default, fio will attempt to catch up to the specified rate setting,
+ if any kind of thinktime setting was used. If this option is set, then
+ fio will ignore the thinktime and continue doing IO at the specified
+ rate, instead of entering a catch-up mode after thinktime is done.
+
I/O latency
~~~~~~~~~~~
*/
static long long usec_for_io(struct thread_data *td, enum fio_ddir ddir)
{
- uint64_t secs, remainder, bps, bytes, iops;
+ uint64_t bps = td->rate_bps[ddir];
assert(!(td->flags & TD_F_CHILD));
- bytes = td->rate_io_issue_bytes[ddir];
- bps = td->rate_bps[ddir];
if (td->o.rate_process == RATE_PROCESS_POISSON) {
- uint64_t val;
+ uint64_t val, iops;
+
iops = bps / td->o.bs[ddir];
val = (int64_t) (1000000 / iops) *
-logf(__rand_0_1(&td->poisson_state[ddir]));
td->last_usec[ddir] += val;
return td->last_usec[ddir];
} else if (bps) {
- secs = bytes / bps;
- remainder = bytes % bps;
+ uint64_t bytes = td->rate_io_issue_bytes[ddir];
+ uint64_t secs = bytes / bps;
+ uint64_t remainder = bytes % bps;
+
return remainder * 1000000 / bps + secs * 1000000;
}
return 0;
}
+static void handle_thinktime(struct thread_data *td, enum fio_ddir ddir)
+{
+ unsigned long long b;
+ uint64_t total;
+ int left;
+
+ b = ddir_rw_sum(td->io_blocks);
+ if (b % td->o.thinktime_blocks)
+ return;
+
+ io_u_quiesce(td);
+
+ total = 0;
+ if (td->o.thinktime_spin)
+ total = usec_spin(td->o.thinktime_spin);
+
+ left = td->o.thinktime - total;
+ if (left)
+ total += usec_sleep(td, left);
+
+ /*
+ * If we're ignoring thinktime for the rate, add the number of bytes
+ * we would have done while sleeping.
+ */
+ if (total && td->rate_bps[ddir] && td->o.rate_ign_think)
+ td->rate_io_issue_bytes[ddir] += (td->rate_bps[ddir] * 1000000) / total;
+}
+
/*
* Main IO worker function. It retrieves io_u's to process and queues
* and reaps them, checking for rate and errors along the way.
int err = PTR_ERR(io_u);
io_u = NULL;
+ ddir = DDIR_INVAL;
if (err == -EBUSY) {
ret = FIO_Q_BUSY;
goto reap;
if (!in_ramp_time(td) && td->o.latency_target)
lat_target_check(td);
- if (td->o.thinktime) {
- unsigned long long b;
-
- b = ddir_rw_sum(td->io_blocks);
- if (!(b % td->o.thinktime_blocks)) {
- int left;
-
- io_u_quiesce(td);
-
- if (td->o.thinktime_spin)
- usec_spin(td->o.thinktime_spin);
-
- left = td->o.thinktime - td->o.thinktime_spin;
- if (left)
- usec_sleep(td, left);
- }
- }
+ if (ddir_rw(ddir) && td->o.thinktime)
+ handle_thinktime(td, ddir);
}
check_update_rusage(td);
o->trim_backlog = le64_to_cpu(top->trim_backlog);
o->rate_process = le32_to_cpu(top->rate_process);
+ o->rate_ign_think = le32_to_cpu(top->rate_ign_think);
for (i = 0; i < FIO_IO_U_LIST_MAX_LEN; i++)
o->percentile_list[i].u.f = fio_uint64_to_double(le64_to_cpu(top->percentile_list[i].u.i));
top->offset_increment = __cpu_to_le64(o->offset_increment);
top->number_ios = __cpu_to_le64(o->number_ios);
top->rate_process = cpu_to_le32(o->rate_process);
+ top->rate_ign_think = cpu_to_le32(o->rate_ign_think);
for (i = 0; i < FIO_IO_U_LIST_MAX_LEN; i++)
top->percentile_list[i].u.i = __cpu_to_le64(fio_double_to_uint64(o->percentile_list[i].u.f));
flow, known as the Poisson process
(\fIhttps://en.wikipedia.org/wiki/Poisson_point_process\fR). The lambda will be
10^6 / IOPS for the given workload.
+.TP
+.BI rate_ignore_thinktime \fR=\fPbool
+By default, fio will attempt to catch up to the specified rate setting, if any
+kind of thinktime setting was used. If this option is set, then fio will
+ignore the thinktime and continue doing IO at the specified rate, instead of
+entering a catch-up mode after thinktime is done.
.SS "I/O latency"
.TP
.BI latency_target \fR=\fPtime
if (td->o.io_submit_mode == IO_MODE_INLINE)
io_u_quiesce(td);
- usec = usec_sleep(td, usec);
-
+ usec_sleep(td, usec);
return ddir;
}
.category = FIO_OPT_C_IO,
.group = FIO_OPT_G_RATE,
},
+ {
+ .name = "rate_ignore_thinktime",
+ .lname = "Rate ignore thinktime",
+ .type = FIO_OPT_BOOL,
+ .off1 = offsetof(struct thread_options, rate_ign_think),
+ .help = "Rated IO ignores thinktime settings",
+ .parent = "rate",
+ .category = FIO_OPT_C_IO,
+ .group = FIO_OPT_G_RATE,
+ },
{
.name = "max_latency",
.lname = "Max Latency (usec)",
};
enum {
- FIO_SERVER_VER = 68,
+ FIO_SERVER_VER = 69,
FIO_SERVER_MAX_FRAGMENT_PDU = 1024,
FIO_SERVER_MAX_CMD_MB = 2048,
unsigned int rate_iops[DDIR_RWDIR_CNT];
unsigned int rate_iops_min[DDIR_RWDIR_CNT];
unsigned int rate_process;
+ unsigned int rate_ign_think;
char *ioscheduler;
uint32_t rate_iops[DDIR_RWDIR_CNT];
uint32_t rate_iops_min[DDIR_RWDIR_CNT];
uint32_t rate_process;
+ uint32_t rate_ign_think;
+ uint32_t pad;
uint8_t ioscheduler[FIO_TOP_STR_MAX];