From: Jan Kara <jack@suse.cz>
To: Vincent Fu <vincentfu@gmail.com>
Cc: Jens Axboe <axboe@kernel.dk>,
fio@vger.kernel.org, Jan Kara <jack@suse.cz>,
Damien Le Moal <dlemoal@kernel.org>
Subject: [PATCH v2 4/5] time: Evaluate ramp up condition once per second
Date: Fri, 19 Dec 2025 14:42:38 +0100 [thread overview]
Message-ID: <20251219134247.14195-4-jack@suse.cz> (raw)
In-Reply-To: <20251219133853.8548-1-jack@suse.cz>
Instead of evaluating whether ramp up period has finished on each IO
submission and completion evaluate it once per second and set
appropriate state variable in thread_data. Later when ramp up period end
condition will be more complex and would involve stat data from all
threads, it would unnecessarily slow down IO.
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Signed-off-by: Jan Kara <jack@suse.cz>
---
fio.h | 2 +-
fio_time.h | 5 ++++
helper_thread.c | 8 +++++-
time.c | 66 +++++++++++++++++++++++++++++++++----------------
4 files changed, 58 insertions(+), 23 deletions(-)
diff --git a/fio.h b/fio.h
index 87c20803a929..fdd36fa49c95 100644
--- a/fio.h
+++ b/fio.h
@@ -417,7 +417,7 @@ struct thread_data {
struct timespec terminate_time;
unsigned int ts_cache_nr;
unsigned int ts_cache_mask;
- bool ramp_period_over;
+ unsigned int ramp_period_state;
/*
* Time since last latency_window was started
diff --git a/fio_time.h b/fio_time.h
index c67c9450f484..54dad8c7812e 100644
--- a/fio_time.h
+++ b/fio_time.h
@@ -8,6 +8,10 @@
/* IWYU pragma: end_exports */
#include "lib/types.h"
+#define RAMP_PERIOD_CHECK_MSEC 1000
+
+extern bool ramp_period_enabled;
+
struct thread_data;
extern uint64_t ntime_since(const struct timespec *, const struct timespec *);
extern uint64_t ntime_since_now(const struct timespec *);
@@ -27,6 +31,7 @@ extern uint64_t usec_spin(unsigned int);
extern uint64_t usec_sleep(struct thread_data *, unsigned long);
extern void fill_start_time(struct timespec *);
extern void set_genesis_time(void);
+extern int ramp_period_check(void);
extern bool ramp_period_over(struct thread_data *);
extern bool in_ramp_period(struct thread_data *);
extern void td_ramp_period_init(struct thread_data *);
diff --git a/helper_thread.c b/helper_thread.c
index fed21d1d61e7..88614e58e5a8 100644
--- a/helper_thread.c
+++ b/helper_thread.c
@@ -290,7 +290,13 @@ static void *helper_thread_main(void *data)
.interval_ms = steadystate_enabled ? ss_check_interval :
0,
.func = steadystate_check,
- }
+ },
+ {
+ .name = "ramp_period",
+ .interval_ms = ramp_period_enabled ?
+ RAMP_PERIOD_CHECK_MSEC : 0,
+ .func = ramp_period_check,
+ },
};
struct timespec ts;
long clk_tck;
diff --git a/time.c b/time.c
index f90f2d9044fc..2709d5b9784a 100644
--- a/time.c
+++ b/time.c
@@ -6,6 +6,12 @@
static struct timespec genesis;
static unsigned long ns_granularity;
+enum ramp_period_states {
+ RAMP_RUNNING,
+ RAMP_FINISHING,
+ RAMP_DONE
+};
+
void timespec_add_msec(struct timespec *ts, unsigned int msec)
{
uint64_t adj_nsec = 1000000ULL * msec;
@@ -112,51 +118,69 @@ uint64_t utime_since_genesis(void)
bool in_ramp_period(struct thread_data *td)
{
- return !td->ramp_period_over;
+ return td->ramp_period_state != RAMP_DONE;
+}
+
+bool ramp_period_enabled = false;
+
+int ramp_period_check(void)
+{
+ for_each_td(td) {
+ if (td->ramp_period_state != RAMP_RUNNING)
+ continue;
+ if (utime_since_now(&td->epoch) >= td->o.ramp_time)
+ td->ramp_period_state = RAMP_FINISHING;
+ } end_for_each();
+
+ return 0;
}
static bool parent_update_ramp(struct thread_data *td)
{
struct thread_data *parent = td->parent;
- if (!parent || parent->ramp_period_over)
+ if (!parent || parent->ramp_period_state == RAMP_DONE)
return false;
reset_all_stats(parent);
- parent->ramp_period_over = true;
+ parent->ramp_period_state = RAMP_DONE;
td_set_runstate(parent, TD_RAMP);
return true;
}
+
bool ramp_period_over(struct thread_data *td)
{
- if (td->ramp_period_over)
+ if (td->ramp_period_state == RAMP_DONE)
return true;
- if (utime_since_now(&td->epoch) >= td->o.ramp_time) {
- td->ramp_period_over = true;
- reset_all_stats(td);
- reset_io_stats(td);
- td_set_runstate(td, TD_RAMP);
+ if (td->ramp_period_state == RAMP_RUNNING)
+ return false;
- /*
- * If we have a parent, the parent isn't doing IO. Hence
- * the parent never enters do_io(), which will switch us
- * from RAMP -> RUNNING. Do this manually here.
- */
- if (parent_update_ramp(td))
- td_set_runstate(td, TD_RUNNING);
+ td->ramp_period_state = RAMP_DONE;
+ reset_all_stats(td);
+ reset_io_stats(td);
+ td_set_runstate(td, TD_RAMP);
- return true;
- }
+ /*
+ * If we have a parent, the parent isn't doing IO. Hence
+ * the parent never enters do_io(), which will switch us
+ * from RAMP -> RUNNING. Do this manually here.
+ */
+ if (parent_update_ramp(td))
+ td_set_runstate(td, TD_RUNNING);
- return false;
+ return true;
}
void td_ramp_period_init(struct thread_data *td)
{
- if (!td->o.ramp_time)
- td->ramp_period_over = true;
+ if (td->o.ramp_time) {
+ td->ramp_period_state = RAMP_RUNNING;
+ ramp_period_enabled = true;
+ } else {
+ td->ramp_period_state = RAMP_DONE;
+ }
}
void fio_time_init(void)
--
2.51.0
next prev parent reply other threads:[~2025-12-19 13:43 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-12-19 13:42 [PATCH v2 0/5] Add support for specifying ramp up period by amount of IO Jan Kara
2025-12-19 13:42 ` [PATCH v2 1/5] time: rename in_ramp_time() and ramp_time_over() Jan Kara
2025-12-19 13:42 ` [PATCH v2 2/5] td: Initialize ramp_period_over based on options Jan Kara
2025-12-19 13:42 ` [PATCH v2 3/5] eta: Use in_ramp_period() instead of opencoding it Jan Kara
2025-12-19 13:42 ` Jan Kara [this message]
2025-12-19 13:42 ` [PATCH v2 5/5] Add option to specify ramp period by amount of IO Jan Kara
2025-12-24 19:44 ` [PATCH v2 0/5] Add support for specifying ramp up " Vincent Fu
2026-01-07 17:02 ` Jan Kara
2026-01-07 21:26 ` Vincent Fu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20251219134247.14195-4-jack@suse.cz \
--to=jack@suse.cz \
--cc=axboe@kernel.dk \
--cc=dlemoal@kernel.org \
--cc=fio@vger.kernel.org \
--cc=vincentfu@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox