Blame SOURCES/0001-Add-option-latency_run-to-continue-enable-latency_ta.patch

701e7e
From e1bcd541f63f9029f6c50116831303ad06292edc Mon Sep 17 00:00:00 2001
701e7e
From: Song Liu <songliubraving@fb.com>
701e7e
Date: Sun, 17 May 2020 22:39:49 -0700
701e7e
Subject: [PATCH] Add option latency_run to continue enable latency_target
701e7e
701e7e
Currently, latency_target run will exist once fio find the highest queue
701e7e
depth that meets latency_target. Add option latency_run. If set, fio will
701e7e
continue running and try to meet latency_target by adusting queue depth.
701e7e
701e7e
Signed-off-by: Song Liu <songliubraving@fb.com>
701e7e
---
701e7e
 HOWTO            |  7 +++++++
701e7e
 cconv.c          |  2 ++
701e7e
 fio.1            |  5 +++++
701e7e
 fio.h            |  1 +
701e7e
 io_u.c           | 18 +++++++++++++++++-
701e7e
 options.c        | 10 ++++++++++
701e7e
 server.h         |  2 +-
701e7e
 thread_options.h |  2 ++
701e7e
 8 files changed, 45 insertions(+), 2 deletions(-)
701e7e
701e7e
diff --git a/HOWTO b/HOWTO
701e7e
index 430c7b62..f0b4ffe4 100644
701e7e
--- a/HOWTO
701e7e
+++ b/HOWTO
701e7e
@@ -2551,6 +2551,13 @@ I/O latency
701e7e
 	defaults to 100.0, meaning that all I/Os must be equal or below to the value
701e7e
 	set by :option:`latency_target`.
701e7e
 
701e7e
+.. option:: latency_run=bool
701e7e
+
701e7e
+	Used with :option:`latency_target`. If false (default), fio will find
701e7e
+	the highest queue depth that meets :option:`latency_target` and exit. If
701e7e
+	true, fio will continue running and try to meet :option:`latency_target`
701e7e
+	by adjusting queue depth.
701e7e
+
701e7e
 .. option:: max_latency=time
701e7e
 
701e7e
 	If set, fio will exit the job with an ETIMEDOUT error if it exceeds this
701e7e
diff --git a/cconv.c b/cconv.c
701e7e
index 48218dc4..449bcf7b 100644
701e7e
--- a/cconv.c
701e7e
+++ b/cconv.c
701e7e
@@ -288,6 +288,7 @@ void convert_thread_options_to_cpu(struct thread_options *o,
701e7e
 	o->latency_window = le64_to_cpu(top->latency_window);
701e7e
 	o->max_latency = le64_to_cpu(top->max_latency);
701e7e
 	o->latency_percentile.u.f = fio_uint64_to_double(le64_to_cpu(top->latency_percentile.u.i));
701e7e
+	o->latency_run = le32_to_cpu(top->latency_run);
701e7e
 	o->compress_percentage = le32_to_cpu(top->compress_percentage);
701e7e
 	o->compress_chunk = le32_to_cpu(top->compress_chunk);
701e7e
 	o->dedupe_percentage = le32_to_cpu(top->dedupe_percentage);
701e7e
@@ -487,6 +488,7 @@ void convert_thread_options_to_net(struct thread_options_pack *top,
701e7e
 	top->latency_window = __cpu_to_le64(o->latency_window);
701e7e
 	top->max_latency = __cpu_to_le64(o->max_latency);
701e7e
 	top->latency_percentile.u.i = __cpu_to_le64(fio_double_to_uint64(o->latency_percentile.u.f));
701e7e
+	top->latency_run = __cpu_to_le32(o->latency_run);
701e7e
 	top->compress_percentage = cpu_to_le32(o->compress_percentage);
701e7e
 	top->compress_chunk = cpu_to_le32(o->compress_chunk);
701e7e
 	top->dedupe_percentage = cpu_to_le32(o->dedupe_percentage);
701e7e
diff --git a/fio.1 b/fio.1
701e7e
index a2379f98..3a7a359b 100644
701e7e
--- a/fio.1
701e7e
+++ b/fio.1
701e7e
@@ -2275,6 +2275,11 @@ The percentage of I/Os that must fall within the criteria specified by
701e7e
 defaults to 100.0, meaning that all I/Os must be equal or below to the value
701e7e
 set by \fBlatency_target\fR.
701e7e
 .TP
701e7e
+.BI latency_run \fR=\fPbool
701e7e
+Used with \fBlatency_target\fR. If false (default), fio will find the highest
701e7e
+queue depth that meets \fBlatency_target\fR and exit. If true, fio will continue
701e7e
+running and try to meet \fBlatency_target\fR by adjusting queue depth.
701e7e
+.TP
701e7e
 .BI max_latency \fR=\fPtime
701e7e
 If set, fio will exit the job with an ETIMEDOUT error if it exceeds this
701e7e
 maximum latency. When the unit is omitted, the value is interpreted in
701e7e
diff --git a/fio.h b/fio.h
701e7e
index bbf057c1..7610026d 100644
701e7e
--- a/fio.h
701e7e
+++ b/fio.h
701e7e
@@ -377,6 +377,7 @@ struct thread_data {
701e7e
 	unsigned int latency_qd_high;
701e7e
 	unsigned int latency_qd_low;
701e7e
 	unsigned int latency_failed;
701e7e
+	unsigned int latency_stable_count;
701e7e
 	uint64_t latency_ios;
701e7e
 	int latency_end_run;
701e7e
 
701e7e
diff --git a/io_u.c b/io_u.c
701e7e
index aa8808b8..ae1438fd 100644
701e7e
--- a/io_u.c
701e7e
+++ b/io_u.c
701e7e
@@ -1391,6 +1391,7 @@ static bool __lat_target_failed(struct thread_data *td)
701e7e
 		td->latency_qd_low--;
701e7e
 
701e7e
 	td->latency_qd = (td->latency_qd + td->latency_qd_low) / 2;
701e7e
+	td->latency_stable_count = 0;
701e7e
 
701e7e
 	dprint(FD_RATE, "Ramped down: %d %d %d\n", td->latency_qd_low, td->latency_qd, td->latency_qd_high);
701e7e
 
701e7e
@@ -1440,6 +1441,21 @@ static void lat_target_success(struct thread_data *td)
701e7e
 
701e7e
 	td->latency_qd_low = td->latency_qd;
701e7e
 
701e7e
+	if (td->latency_qd + 1 == td->latency_qd_high) {
701e7e
+		/*
701e7e
+		 * latency_qd will not incease on lat_target_success(), so
701e7e
+		 * called stable. If we stick with this queue depth, the
701e7e
+		 * final latency is likely lower than latency_target. Fix
701e7e
+		 * this by increasing latency_qd_high slowly. Use a naive
701e7e
+		 * heuristic here. If we get lat_target_success() 3 times
701e7e
+		 * in a row, increase latency_qd_high by 1.
701e7e
+		 */
701e7e
+		if (++td->latency_stable_count >= 3) {
701e7e
+			td->latency_qd_high++;
701e7e
+			td->latency_stable_count = 0;
701e7e
+		}
701e7e
+	}
701e7e
+
701e7e
 	/*
701e7e
 	 * If we haven't failed yet, we double up to a failing value instead
701e7e
 	 * of bisecting from highest possible queue depth. If we have set
701e7e
@@ -1459,7 +1475,7 @@ static void lat_target_success(struct thread_data *td)
701e7e
 	 * Same as last one, we are done. Let it run a latency cycle, so
701e7e
 	 * we get only the results from the targeted depth.
701e7e
 	 */
701e7e
-	if (td->latency_qd == qd) {
701e7e
+	if (!o->latency_run && td->latency_qd == qd) {
701e7e
 		if (td->latency_end_run) {
701e7e
 			dprint(FD_RATE, "We are done\n");
701e7e
 			td->done = 1;
701e7e
diff --git a/options.c b/options.c
701e7e
index b18cea33..da401aed 100644
701e7e
--- a/options.c
701e7e
+++ b/options.c
701e7e
@@ -3672,6 +3672,16 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
701e7e
 		.category = FIO_OPT_C_IO,
701e7e
 		.group	= FIO_OPT_G_LATPROF,
701e7e
 	},
701e7e
+	{
701e7e
+		.name	= "latency_run",
701e7e
+		.lname	= "Latency Run",
701e7e
+		.type	= FIO_OPT_BOOL,
701e7e
+		.off1	= offsetof(struct thread_options, latency_run),
701e7e
+		.help	= "Keep adjusting queue depth to match latency_target",
701e7e
+		.def	= "0",
701e7e
+		.category = FIO_OPT_C_IO,
701e7e
+		.group	= FIO_OPT_G_LATPROF,
701e7e
+	},
701e7e
 	{
701e7e
 		.name	= "invalidate",
701e7e
 		.lname	= "Cache invalidate",
701e7e
diff --git a/server.h b/server.h
701e7e
index 279b6917..de01a5c8 100644
701e7e
--- a/server.h
701e7e
+++ b/server.h
701e7e
@@ -48,7 +48,7 @@ struct fio_net_cmd_reply {
701e7e
 };
701e7e
 
701e7e
 enum {
701e7e
-	FIO_SERVER_VER			= 82,
701e7e
+	FIO_SERVER_VER			= 83,
701e7e
 
701e7e
 	FIO_SERVER_MAX_FRAGMENT_PDU	= 1024,
701e7e
 	FIO_SERVER_MAX_CMD_MB		= 2048,
701e7e
diff --git a/thread_options.h b/thread_options.h
701e7e
index c78ed43d..09ccd5b2 100644
701e7e
--- a/thread_options.h
701e7e
+++ b/thread_options.h
701e7e
@@ -324,6 +324,7 @@ struct thread_options {
701e7e
 	unsigned long long latency_target;
701e7e
 	unsigned long long latency_window;
701e7e
 	fio_fp64_t latency_percentile;
701e7e
+	uint32_t latency_run;
701e7e
 
701e7e
 	unsigned int sig_figs;
701e7e
 
701e7e
@@ -612,6 +613,7 @@ struct thread_options_pack {
701e7e
 	uint64_t latency_window;
701e7e
 	uint64_t max_latency;
701e7e
 	fio_fp64_t latency_percentile;
701e7e
+	uint32_t latency_run;
701e7e
 
701e7e
 	uint32_t sig_figs;
701e7e
 
701e7e
-- 
701e7e
2.17.0
701e7e