bandwidth rate stepping

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

I'm wanting to use fio to test the latency of a storage system at various bandwidths. While I could use a script to run fio repeatedly at various rate= settings, that would give the storage device some "settle" time between tests, and I'd prefer to keep the test running constantly.

I've added this feature to my local copy, and it *just about* works ;) Config file and patch attached. Here's my problem: I'm getting a blip in bandwidth every time I step up the rate. This is very obvious when used with low rates/steps, like the config file below.

Second problem, at high rates/steps (like 1m/1m), bandwidth logging gets messed up. While tracking this down, it appeared that after the first rate step, td->bw_sample_time was getting reset every 250ms whereas the default bw_avg_time is 500ms, hence no logging. (Note: if I analyze the latency logs, it appears the stepping did actually work correctly, and with no spikes.)

As I keep messing with this, it's clear I don't fully understand the interaction between my change and the big loop in thread_main(). Can someone here take a look at my changes and give me some guidance?

Many thanks,
Josh


-- fio job file

[global]
thread
ioengine=null
size=1m
time_based
runtime=30s
write_bw_log
write_lat_log

[ratestep]
rw=write
rate=,10k
ratestep=,5k
bs=4k


- Adding "ratestep=" option to config files; when used with "rate="
  option, it will step the rate up by ratestep every (ratecycle * 5)
  milliseconds. (Yea, should make the step interval configurable
  separately.)

- Added step_rate() near the end of do_io(), just after we do the
  check_min_rate() part.

Currently very fiddly; seems to get blips in bandwidth just after a
rate step, also at high rates/steps it messes up bandwidth logging.
Need feedback from mailing list.
---
 fio.c     |   40 ++++++++++++++++++++++++++++++++++++++++
 fio.h     |    4 +++-
 init.c    |    4 ++++
 options.c |    8 ++++++++
 4 files changed, 55 insertions(+), 1 deletions(-)

diff --git a/fio.c b/fio.c
index 5b58ab8..9063c03 100644
--- a/fio.c
+++ b/fio.c
@@ -341,6 +341,39 @@ static int check_min_rate(struct thread_data *td, struct timeval *now,
 	return ret;
 }
 
+static int __step_rate(struct thread_data *td, struct timeval *now,
+		       enum fio_ddir ddir)
+{
+        unsigned long spent;
+        unsigned long long new_rate;
+	
+	assert(ddir_rw(ddir));
+
+	if (!td->o.ratestep[ddir])
+		return 0;
+
+	spent = mtime_since(&td->lastratestep[ddir], now);
+
+	if (spent < td->o.ratecycle * 5)
+	        return 0;
+		
+        new_rate = td->rate_bps[ddir] + td->o.ratestep[ddir];
+        td->o.rate[ddir] = td->rate_bps[ddir] = new_rate;
+
+	memcpy(&td->lastratestep[ddir], now, sizeof(*now));
+	return 0;
+}
+
+static int step_rate(struct thread_data *td, struct timeval *now)
+{
+	int ret = 0;
+
+	ret |= __step_rate(td, now, DDIR_READ);
+	ret |= __step_rate(td, now, DDIR_WRITE);
+
+	return ret;
+}
+
 static inline int runtime_exceeded(struct thread_data *td, struct timeval *t)
 {
 	if (!td->o.timeout)
@@ -813,6 +846,8 @@ sync_done:
 				td_verror(td, EIO, "check_min_rate");
 				break;
 			}
+			
+                        step_rate(td, &comp_time);
 		}
 
 		if (td->o.thinktime) {
@@ -1237,6 +1272,11 @@ static void *thread_main(void *data)
 	fio_gettime(&td->epoch, NULL);
 	getrusage(RUSAGE_SELF, &td->ru_start);
 
+	if (td->o.ratestep[0] || td->o.ratestep[1]) {
+		memcpy(&td->lastratestep[0], &td->epoch, sizeof(td->epoch));
+		memcpy(&td->lastratestep[1], &td->epoch, sizeof(td->epoch));
+	}
+
 	clear_state = 0;
 	while (keep_running(td)) {
 		fio_gettime(&td->start, NULL);
diff --git a/fio.h b/fio.h
index cc1f65f..36b15aa 100644
--- a/fio.h
+++ b/fio.h
@@ -212,6 +212,7 @@ struct thread_options {
 
 	unsigned int rate[2];
 	unsigned int ratemin[2];
+	unsigned int ratestep[2];
 	unsigned int ratecycle;
 	unsigned int rate_iops[2];
 	unsigned int rate_iops_min[2];
@@ -361,6 +362,7 @@ struct thread_data {
 	unsigned long rate_bytes[2];
 	unsigned long rate_blocks[2];
 	struct timeval lastrate[2];
+    struct timeval lastratestep[2];
 
 	unsigned long long total_io_size;
 	unsigned long long fill_device_size;
@@ -659,7 +661,7 @@ static inline int __should_check_rate(struct thread_data *td,
 	 * If some rate setting was given, we need to check it
 	 */
 	if (o->rate[ddir] || o->ratemin[ddir] || o->rate_iops[ddir] ||
-	    o->rate_iops_min[ddir])
+	    o->rate_iops_min[ddir] || o->ratestep[ddir])
 		return 1;
 
 	return 0;
diff --git a/init.c b/init.c
index 482ce09..717dfc5 100644
--- a/init.c
+++ b/init.c
@@ -498,6 +498,10 @@ static int fixup_options(struct thread_data *td)
 		log_err("fio: minimum rate exceeds rate\n");
 		ret = 1;
 	}
+	if ((o->ratestep[0] && !o->rate[0]) || (o->ratestep[1] && !o->rate[1])) {
+		log_err("fio: ratestep requires initial rate also set\n");
+                ret = 1;
+	}
 
 	if (!o->timeout && o->time_based) {
 		log_err("fio: time_based requires a runtime/timeout setting\n");
diff --git a/options.c b/options.c
index 53c3a82..a276bcb 100644
--- a/options.c
+++ b/options.c
@@ -1772,6 +1772,14 @@ static struct fio_option options[FIO_MAX_OPTS] = {
 		.help	= "Job must meet this rate or it will be shutdown",
 		.parent	= "rate",
 	},
+        {
+        	.name	= "ratestep",
+        	.type	= FIO_OPT_INT,
+        	.off1	= td_var_offset(ratestep[0]),
+        	.off2	= td_var_offset(ratestep[1]),
+        	.help	= "Job will increment bandwidth rate by this amount each ratecycle",
+        	.parent	= "rate",
+        },
 	{
 		.name	= "rate_iops",
 		.type	= FIO_OPT_INT,
-- 
1.7.4.4


--
To unsubscribe from this list: send the line "unsubscribe fio" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Kernel]     [Linux SCSI]     [Linux IDE]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux SCSI]

  Powered by Linux