* [PATCH v3] options: Add thinktime_iotime option
@ 2021-09-06 1:50 Shin'ichiro Kawasaki
2021-09-06 3:11 ` Jens Axboe
0 siblings, 1 reply; 2+ messages in thread
From: Shin'ichiro Kawasaki @ 2021-09-06 1:50 UTC (permalink / raw)
To: fio, Jens Axboe; +Cc: Damien Le Moal, Shinichiro Kawasaki
The thinktime option allows stalling a job for a specified amount of
time. Using the thinktime_blocks option, periodic stalls can be added
every thinktime_blocks IOs. However, with this option, the periodic
stall may not be repeated at equal time intervals as the time to execute
thinktime_blocks IOs may vary.
To control the thinktime interval by time, introduce the option
thinktime_iotime. With this new option, the thinktime stall is repeated
after IOs are executed for thinktime_iotime. If this option is used
together with the thinktime_blocks option, the thinktime pause is
repeated after thinktime_iotime or after thinktime_blocks IOs, whichever
happens first.
To support the new option, add a new member thinktime_iotime in the
struct thread_options and the struct thread_options_pack. Avoid size
increase of the struct thread_options_pack by replacing a padding 'pad5'
with the new member. To keep thinktime related members close, move the
members near the position where the padding was placed. Make same
changes to the struct thread_option also for consistency.
To track the time and IO block count at the last stall, add
last_thinktime variable and last_thinktime_blocks variable to struct
thread_data. Also, introduce the helper function init_thinktime()
to group thinktime related preparations.
Signed-off-by: Shin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com>
---
Changes from v2:
* Improved descriptions in fio.1 and HOWTO
* Fixed order of members added to fio_options
* Rebased to the master branch tip
Changes from v1:
* Moved thinktime related members in thread_options_pack to avoid padding
HOWTO | 14 +++++++++++++-
backend.c | 45 +++++++++++++++++++++++++++++++++++++++------
cconv.c | 2 ++
fio.1 | 13 ++++++++++++-
fio.h | 2 ++
options.c | 14 ++++++++++++++
server.h | 2 +-
thread_options.h | 21 ++++++++++++---------
8 files changed, 95 insertions(+), 18 deletions(-)
diff --git a/HOWTO b/HOWTO
index 1853f56a..297a0485 100644
--- a/HOWTO
+++ b/HOWTO
@@ -2745,7 +2745,7 @@ I/O rate
Stall the job for the specified period of time after an I/O has completed before issuing the
next. May be used to simulate processing being done by an application.
When the unit is omitted, the value is interpreted in microseconds. See
- :option:`thinktime_blocks` and :option:`thinktime_spin`.
+ :option:`thinktime_blocks`, :option:`thinktime_iotime` and :option:`thinktime_spin`.
.. option:: thinktime_spin=time
@@ -2770,6 +2770,18 @@ I/O rate
:option:`thinktime_blocks` blocks. If this is set to `issue`, then the trigger happens
at the issue side.
+.. option:: thinktime_iotime=time
+
+ Only valid if :option:`thinktime` is set - control :option:`thinktime`
+ interval by time. The :option:`thinktime` stall is repeated after IOs
+ are executed for :option:`thinktime_iotime`. For example,
+ ``--thinktime_iotime=9s --thinktime=1s`` repeat 10-second cycle with IOs
+ for 9 seconds and stall for 1 second. When the unit is omitted,
+ :option:`thinktime_iotime` is interpreted as a number of seconds. If
+ this option is used together with :option:`thinktime_blocks`, the
+ :option:`thinktime` stall is repeated after :option:`thinktime_iotime`
+ or after :option:`thinktime_blocks` IOs, whichever happens first.
+
.. option:: rate=int[,int][,int]
Cap the bandwidth used by this job. The number is in bytes/sec, the normal
diff --git a/backend.c b/backend.c
index 1bcb035a..86fa6d41 100644
--- a/backend.c
+++ b/backend.c
@@ -858,15 +858,47 @@ static long long usec_for_io(struct thread_data *td, enum fio_ddir ddir)
return 0;
}
+static void init_thinktime(struct thread_data *td)
+{
+ if (td->o.thinktime_blocks_type == THINKTIME_BLOCKS_TYPE_COMPLETE)
+ td->thinktime_blocks_counter = td->io_blocks;
+ else
+ td->thinktime_blocks_counter = td->io_issues;
+ td->last_thinktime = td->epoch;
+ td->last_thinktime_blocks = 0;
+}
+
static void handle_thinktime(struct thread_data *td, enum fio_ddir ddir,
struct timespec *time)
{
unsigned long long b;
uint64_t total;
int left;
+ struct timespec now;
+ bool stall = false;
+
+ if (td->o.thinktime_iotime) {
+ fio_gettime(&now, NULL);
+ if (utime_since(&td->last_thinktime, &now)
+ >= td->o.thinktime_iotime + td->o.thinktime) {
+ stall = true;
+ } else if (!fio_option_is_set(&td->o, thinktime_blocks)) {
+ /*
+ * When thinktime_iotime is set and thinktime_blocks is
+ * not set, skip the thinktime_blocks check, since
+ * thinktime_blocks default value 1 does not work
+ * together with thinktime_iotime.
+ */
+ return;
+ }
+
+ }
b = ddir_rw_sum(td->thinktime_blocks_counter);
- if (b % td->o.thinktime_blocks || !b)
+ if (b >= td->last_thinktime_blocks + td->o.thinktime_blocks)
+ stall = true;
+
+ if (!stall)
return;
io_u_quiesce(td);
@@ -902,6 +934,10 @@ static void handle_thinktime(struct thread_data *td, enum fio_ddir ddir,
if (time && should_check_rate(td))
fio_gettime(time, NULL);
+
+ td->last_thinktime_blocks = b;
+ if (td->o.thinktime_iotime)
+ td->last_thinktime = now;
}
/*
@@ -1792,17 +1828,14 @@ static void *thread_main(void *data)
if (rate_submit_init(td, sk_out))
goto err;
- if (td->o.thinktime_blocks_type == THINKTIME_BLOCKS_TYPE_COMPLETE)
- td->thinktime_blocks_counter = td->io_blocks;
- else
- td->thinktime_blocks_counter = td->io_issues;
-
set_epoch_time(td, o->log_unix_epoch);
fio_getrusage(&td->ru_start);
memcpy(&td->bw_sample_time, &td->epoch, sizeof(td->epoch));
memcpy(&td->iops_sample_time, &td->epoch, sizeof(td->epoch));
memcpy(&td->ss.prev_time, &td->epoch, sizeof(td->epoch));
+ init_thinktime(td);
+
if (o->ratemin[DDIR_READ] || o->ratemin[DDIR_WRITE] ||
o->ratemin[DDIR_TRIM]) {
memcpy(&td->lastrate[DDIR_READ], &td->bw_sample_time,
diff --git a/cconv.c b/cconv.c
index 2dc5274e..2104308c 100644
--- a/cconv.c
+++ b/cconv.c
@@ -214,6 +214,7 @@ void convert_thread_options_to_cpu(struct thread_options *o,
o->thinktime_spin = le32_to_cpu(top->thinktime_spin);
o->thinktime_blocks = le32_to_cpu(top->thinktime_blocks);
o->thinktime_blocks_type = le32_to_cpu(top->thinktime_blocks_type);
+ o->thinktime_iotime = le32_to_cpu(top->thinktime_iotime);
o->fsync_blocks = le32_to_cpu(top->fsync_blocks);
o->fdatasync_blocks = le32_to_cpu(top->fdatasync_blocks);
o->barrier_blocks = le32_to_cpu(top->barrier_blocks);
@@ -440,6 +441,7 @@ void convert_thread_options_to_net(struct thread_options_pack *top,
top->thinktime_spin = cpu_to_le32(o->thinktime_spin);
top->thinktime_blocks = cpu_to_le32(o->thinktime_blocks);
top->thinktime_blocks_type = __cpu_to_le32(o->thinktime_blocks_type);
+ top->thinktime_iotime = __cpu_to_le32(o->thinktime_iotime);
top->fsync_blocks = cpu_to_le32(o->fsync_blocks);
top->fdatasync_blocks = cpu_to_le32(o->fdatasync_blocks);
top->barrier_blocks = cpu_to_le32(o->barrier_blocks);
diff --git a/fio.1 b/fio.1
index 03fddffb..78988c9e 100644
--- a/fio.1
+++ b/fio.1
@@ -2499,7 +2499,7 @@ problem). Note that this option cannot reliably be used with async IO engines.
Stall the job for the specified period of time after an I/O has completed before issuing the
next. May be used to simulate processing being done by an application.
When the unit is omitted, the value is interpreted in microseconds. See
-\fBthinktime_blocks\fR and \fBthinktime_spin\fR.
+\fBthinktime_blocks\fR, \fBthinktime_iotime\fR and \fBthinktime_spin\fR.
.TP
.BI thinktime_spin \fR=\fPtime
Only valid if \fBthinktime\fR is set - pretend to spend CPU time doing
@@ -2520,6 +2520,17 @@ Only valid if \fBthinktime\fR is set - control how \fBthinktime_blocks\fR trigge
The default is `complete', which triggers \fBthinktime\fR when fio completes
\fBthinktime_blocks\fR blocks. If this is set to `issue', then the trigger happens
at the issue side.
+.TP
+.BI thinktime_iotime \fR=\fPtime
+Only valid if \fBthinktime\fR is set - control \fBthinktime\fR interval by time.
+The \fBthinktime\fR stall is repeated after IOs are executed for
+\fBthinktime_iotime\fR. For example, `\-\-thinktime_iotime=9s \-\-thinktime=1s'
+repeat 10-second cycle with IOs for 9 seconds and stall for 1 second. When the
+unit is omitted, \fBthinktime_iotime\fR is interpreted as a number of seconds.
+If this option is used together with \fBthinktime_blocks\fR, the \fBthinktime\fR
+stall is repeated after \fBthinktime_iotime\fR or after \fBthinktime_blocks\fR
+IOs, whichever happens first.
+
.TP
.BI rate \fR=\fPint[,int][,int]
Cap the bandwidth used by this job. The number is in bytes/sec, the normal
diff --git a/fio.h b/fio.h
index da1fe085..6bb21ebb 100644
--- a/fio.h
+++ b/fio.h
@@ -370,6 +370,8 @@ struct thread_data {
uint64_t bytes_done[DDIR_RWDIR_CNT];
uint64_t *thinktime_blocks_counter;
+ struct timespec last_thinktime;
+ uint64_t last_thinktime_blocks;
/*
* State for random io, a bitmap of blocks done vs not done
diff --git a/options.c b/options.c
index 74ac1f3f..460cf4ff 100644
--- a/options.c
+++ b/options.c
@@ -3680,6 +3680,20 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
},
.parent = "thinktime",
},
+ {
+ .name = "thinktime_iotime",
+ .lname = "Thinktime interval",
+ .type = FIO_OPT_INT,
+ .off1 = offsetof(struct thread_options, thinktime_iotime),
+ .help = "IO time interval between 'thinktime'",
+ .def = "0",
+ .parent = "thinktime",
+ .hide = 1,
+ .is_seconds = 1,
+ .is_time = 1,
+ .category = FIO_OPT_C_IO,
+ .group = FIO_OPT_G_THINKTIME,
+ },
{
.name = "rate",
.lname = "I/O rate",
diff --git a/server.h b/server.h
index 3ff32d9a..44b8da12 100644
--- a/server.h
+++ b/server.h
@@ -48,7 +48,7 @@ struct fio_net_cmd_reply {
};
enum {
- FIO_SERVER_VER = 93,
+ FIO_SERVER_VER = 94,
FIO_SERVER_MAX_FRAGMENT_PDU = 1024,
FIO_SERVER_MAX_CMD_MB = 2048,
diff --git a/thread_options.h b/thread_options.h
index 9990ab9b..6e1a2cdd 100644
--- a/thread_options.h
+++ b/thread_options.h
@@ -191,10 +191,6 @@ struct thread_options {
unsigned int hugepage_size;
unsigned long long rw_min_bs;
- unsigned int thinktime;
- unsigned int thinktime_spin;
- unsigned int thinktime_blocks;
- unsigned int thinktime_blocks_type;
unsigned int fsync_blocks;
unsigned int fdatasync_blocks;
unsigned int barrier_blocks;
@@ -303,6 +299,12 @@ struct thread_options {
char *exec_prerun;
char *exec_postrun;
+ unsigned int thinktime;
+ unsigned int thinktime_spin;
+ unsigned int thinktime_blocks;
+ unsigned int thinktime_blocks_type;
+ unsigned int thinktime_iotime;
+
uint64_t rate[DDIR_RWDIR_CNT];
uint64_t ratemin[DDIR_RWDIR_CNT];
unsigned int ratecycle;
@@ -504,10 +506,6 @@ struct thread_options_pack {
uint32_t hugepage_size;
uint64_t rw_min_bs;
- uint32_t thinktime;
- uint32_t thinktime_spin;
- uint32_t thinktime_blocks;
- uint32_t thinktime_blocks_type;
uint32_t fsync_blocks;
uint32_t fdatasync_blocks;
uint32_t barrier_blocks;
@@ -612,6 +610,12 @@ struct thread_options_pack {
uint8_t exec_prerun[FIO_TOP_STR_MAX];
uint8_t exec_postrun[FIO_TOP_STR_MAX];
+ uint32_t thinktime;
+ uint32_t thinktime_spin;
+ uint32_t thinktime_blocks;
+ uint32_t thinktime_blocks_type;
+ uint32_t thinktime_iotime;
+
uint64_t rate[DDIR_RWDIR_CNT];
uint64_t ratemin[DDIR_RWDIR_CNT];
uint32_t ratecycle;
@@ -651,7 +655,6 @@ struct thread_options_pack {
uint64_t latency_target;
uint64_t latency_window;
uint64_t max_latency[DDIR_RWDIR_CNT];
- uint32_t pad5;
fio_fp64_t latency_percentile;
uint32_t latency_run;
--
2.31.1
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH v3] options: Add thinktime_iotime option
2021-09-06 1:50 [PATCH v3] options: Add thinktime_iotime option Shin'ichiro Kawasaki
@ 2021-09-06 3:11 ` Jens Axboe
0 siblings, 0 replies; 2+ messages in thread
From: Jens Axboe @ 2021-09-06 3:11 UTC (permalink / raw)
To: Shin'ichiro Kawasaki, fio; +Cc: Damien Le Moal
On 9/5/21 7:50 PM, Shin'ichiro Kawasaki wrote:
> The thinktime option allows stalling a job for a specified amount of
> time. Using the thinktime_blocks option, periodic stalls can be added
> every thinktime_blocks IOs. However, with this option, the periodic
> stall may not be repeated at equal time intervals as the time to execute
> thinktime_blocks IOs may vary.
>
> To control the thinktime interval by time, introduce the option
> thinktime_iotime. With this new option, the thinktime stall is repeated
> after IOs are executed for thinktime_iotime. If this option is used
> together with the thinktime_blocks option, the thinktime pause is
> repeated after thinktime_iotime or after thinktime_blocks IOs, whichever
> happens first.
>
> To support the new option, add a new member thinktime_iotime in the
> struct thread_options and the struct thread_options_pack. Avoid size
> increase of the struct thread_options_pack by replacing a padding 'pad5'
> with the new member. To keep thinktime related members close, move the
> members near the position where the padding was placed. Make same
> changes to the struct thread_option also for consistency.
>
> To track the time and IO block count at the last stall, add
> last_thinktime variable and last_thinktime_blocks variable to struct
> thread_data. Also, introduce the helper function init_thinktime()
> to group thinktime related preparations.
Applied, thanks.
--
Jens Axboe
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2021-09-06 3:12 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-09-06 1:50 [PATCH v3] options: Add thinktime_iotime option Shin'ichiro Kawasaki
2021-09-06 3:11 ` Jens Axboe
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.