Recent changes

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

 



The following changes since commit 55ed9636e82b8dee419b5a76c07098bff4d980b6:

  Fix parser bug dealing with range options and postfix (2011-03-27 20:55:09 +0200)

are available in the git repository at:
  git://git.kernel.dk/fio.git master

Jens Axboe (3):
      Switch to using our internal Tausworthe based random generator for offsets
      Switch the latter part of the offset generation to __rand() too
      Switch all random generators to be decided by use_os_rand

 HOWTO       |    6 ++++++
 filesetup.c |   13 ++++++++++---
 fio.1       |    6 ++++++
 fio.h       |   33 +++++++++++++++++++++++++++------
 init.c      |   31 ++++++++++++++++++++++++++++++-
 io_u.c      |   57 +++++++++++++++++++++++++++++++++++++++++++++------------
 lib/rand.c  |   32 ++++++++++++++++++++------------
 lib/rand.h  |    3 +++
 options.c   |    8 ++++++++
 trim.c      |   11 ++++++++---
 10 files changed, 163 insertions(+), 37 deletions(-)

---

Diff of recent changes:

diff --git a/HOWTO b/HOWTO
index d4e7092..69b8cc6 100644
--- a/HOWTO
+++ b/HOWTO
@@ -348,6 +348,12 @@ kb_base=int	The base unit for a kilobyte. The defacto base is 2^10, 1024.
 randrepeat=bool	For random IO workloads, seed the generator in a predictable
 		way so that results are repeatable across repetitions.
 
+use_os_rand=bool Fio can either use the random generator supplied by the OS
+		to generator random offsets, or it can use it's own internal
+		generator (based on Tausworthe). Default is to use the
+		internal generator, which is often of better quality and
+		faster.
+
 fallocate=bool	By default, fio will use fallocate() to advise the system
 		of the size of the file we are going to write. This can be
 		turned off with fallocate=0. May not be available on all
diff --git a/filesetup.c b/filesetup.c
index 0454cc4..2b690c8 100644
--- a/filesetup.c
+++ b/filesetup.c
@@ -210,9 +210,16 @@ static unsigned long long get_rand_file_size(struct thread_data *td)
 	unsigned long long ret, sized;
 	long r;
 
-	r = os_random_long(&td->file_size_state);
-	sized = td->o.file_size_high - td->o.file_size_low;
-	ret = (unsigned long long) ((double) sized * (r / (OS_RAND_MAX + 1.0)));
+	if (td->o.use_os_rand) {
+		r = os_random_long(&td->file_size_state);
+		sized = td->o.file_size_high - td->o.file_size_low;
+		ret = (unsigned long long) ((double) sized * (r / (OS_RAND_MAX + 1.0)));
+	} else {
+		r = __rand(&td->__file_size_state);
+		sized = td->o.file_size_high - td->o.file_size_low;
+		ret = (unsigned long long) ((double) sized * (r / (FRAND_MAX + 1.0)));
+	}
+
 	ret += td->o.file_size_low;
 	ret -= (ret % td->o.rw_min_bs);
 	return ret;
diff --git a/fio.1 b/fio.1
index a8c0027..0ced604 100644
--- a/fio.1
+++ b/fio.1
@@ -214,6 +214,12 @@ reasons. Allow values are 1024 or 1000, with 1024 being the default.
 Seed the random number generator in a predictable way so results are repeatable
 across runs.  Default: true.
 .TP
+.BI use_os_rand \fR=\fPbool
+Fio can either use the random generator supplied by the OS to generator random
+offsets, or it can use it's own internal generator (based on Tausworthe).
+Default is to use the internal generator, which is often of better quality and
+faster. Default: false.
+.TP
 .BI fallocate \fR=\fPbool
 By default, fio will use fallocate() to advise the system of the size of the
 file we are going to write. This can be turned off with fallocate=0. May not
diff --git a/fio.h b/fio.h
index 08f1733..c0087e8 100644
--- a/fio.h
+++ b/fio.h
@@ -34,6 +34,7 @@ struct thread_data;
 #include "profile.h"
 #include "time.h"
 #include "lib/getopt.h"
+#include "lib/rand.h"
 
 #ifdef FIO_HAVE_GUASI
 #include <guasi.h>
@@ -206,6 +207,7 @@ struct thread_options {
 	unsigned int do_disk_util;
 	unsigned int override_sync;
 	unsigned int rand_repeatable;
+	unsigned int use_os_rand;
 	unsigned int write_lat_log;
 	unsigned int write_bw_log;
 	unsigned int norandommap;
@@ -334,6 +336,7 @@ struct thread_data {
 	union {
 		unsigned int next_file;
 		os_random_state_t next_file_state;
+		struct frand_state __next_file_state;
 	};
 	int error;
 	int done;
@@ -357,9 +360,18 @@ struct thread_data {
 
 	unsigned long rand_seeds[7];
 
-	os_random_state_t bsrange_state;
-	os_random_state_t verify_state;
-	os_random_state_t trim_state;
+	union {
+		os_random_state_t bsrange_state;
+		struct frand_state __bsrange_state;
+	};
+	union {
+		os_random_state_t verify_state;
+		struct frand_state __verify_state;
+	};
+	union {
+		os_random_state_t trim_state;
+		struct frand_state __trim_state;
+	};
 
 	unsigned int verify_batch;
 	unsigned int trim_batch;
@@ -415,7 +427,10 @@ struct thread_data {
 	/*
 	 * State for random io, a bitmap of blocks done vs not done
 	 */
-	os_random_state_t random_state;
+	union {
+		os_random_state_t random_state;
+		struct frand_state __random_state;
+	};
 
 	struct timeval start;	/* start of this loop */
 	struct timeval epoch;	/* time job was started */
@@ -428,7 +443,10 @@ struct thread_data {
 	/*
 	 * read/write mixed workload state
 	 */
-	os_random_state_t rwmix_state;
+	union {
+		os_random_state_t rwmix_state;
+		struct frand_state __rwmix_state;
+	};
 	unsigned long rwmix_issues;
 	enum fio_ddir rwmix_ddir;
 	unsigned int ddir_seq_nr;
@@ -464,7 +482,10 @@ struct thread_data {
 	/*
 	 * For generating file sizes
 	 */
-	os_random_state_t file_size_state;
+	union {
+		os_random_state_t file_size_state;
+		struct frand_state __file_size_state;
+	};
 
 	/*
 	 * Error counts
diff --git a/init.c b/init.c
index 327a3c5..b96350a 100644
--- a/init.c
+++ b/init.c
@@ -463,7 +463,7 @@ static int exists_and_not_file(const char *filename)
 	return 1;
 }
 
-void td_fill_rand_seeds(struct thread_data *td)
+static void td_fill_rand_seeds_os(struct thread_data *td)
 {
 	os_random_seed(td->rand_seeds[0], &td->bsrange_state);
 	os_random_seed(td->rand_seeds[1], &td->verify_state);
@@ -484,6 +484,35 @@ void td_fill_rand_seeds(struct thread_data *td)
 	os_random_seed(td->rand_seeds[4], &td->random_state);
 }
 
+static void td_fill_rand_seeds_internal(struct thread_data *td)
+{
+	init_rand_seed(&td->__bsrange_state, td->rand_seeds[0]);
+	init_rand_seed(&td->__verify_state, td->rand_seeds[1]);
+	init_rand_seed(&td->__rwmix_state, td->rand_seeds[2]);
+
+	if (td->o.file_service_type == FIO_FSERVICE_RANDOM)
+		init_rand_seed(&td->__next_file_state, td->rand_seeds[3]);
+
+	init_rand_seed(&td->__file_size_state, td->rand_seeds[5]);
+	init_rand_seed(&td->__trim_state, td->rand_seeds[6]);
+
+	if (!td_random(td))
+		return;
+
+	if (td->o.rand_repeatable)
+		td->rand_seeds[4] = FIO_RANDSEED * td->thread_number;
+
+	init_rand_seed(&td->__random_state, td->rand_seeds[4]);
+}
+
+void td_fill_rand_seeds(struct thread_data *td)
+{
+	if (td->o.use_os_rand)
+		td_fill_rand_seeds_os(td);
+	else
+		td_fill_rand_seeds_internal(td);
+}
+
 /*
  * Initialize the various random states we need (random io, block size ranges,
  * read/write mix, etc).
diff --git a/io_u.c b/io_u.c
index 5a3ca74..787f382 100644
--- a/io_u.c
+++ b/io_u.c
@@ -168,9 +168,16 @@ static int get_next_rand_offset(struct thread_data *td, struct fio_file *f,
 		goto ffz;
 
 	do {
-		r = os_random_long(&td->random_state);
+		if (td->o.use_os_rand) {
+			r = os_random_long(&td->random_state);
+			*b = (lastb - 1) * (r / ((unsigned long long) OS_RAND_MAX + 1.0));
+		} else {
+			r = __rand(&td->__random_state);
+			*b = (lastb - 1) * (r / ((unsigned long long) FRAND_MAX + 1.0));
+		}
+
 		dprint(FD_RANDOM, "off rand %llu\n", r);
-		*b = (lastb - 1) * (r / ((unsigned long long) OS_RAND_MAX + 1.0));
+
 
 		/*
 		 * if we are not maintaining a random map, we are done.
@@ -203,7 +210,10 @@ static int get_next_rand_offset(struct thread_data *td, struct fio_file *f,
 		if (!get_next_free_block(td, f, ddir, b))
 			goto ret;
 
-		r = os_random_long(&td->random_state);
+		if (td->o.use_os_rand)
+			r = os_random_long(&td->random_state);
+		else
+			r = __rand(&td->__random_state);
 	} while (--loops);
 
 	/*
@@ -336,20 +346,29 @@ static unsigned int __get_next_buflen(struct thread_data *td, struct io_u *io_u)
 	const int ddir = io_u->ddir;
 	unsigned int uninitialized_var(buflen);
 	unsigned int minbs, maxbs;
-	long r;
+	long r, rand_max;
 
 	assert(ddir_rw(ddir));
 
 	minbs = td->o.min_bs[ddir];
 	maxbs = td->o.max_bs[ddir];
 
+	if (td->o.use_os_rand)
+		rand_max = OS_RAND_MAX;
+	else
+		rand_max = FRAND_MAX;
+
 	if (minbs == maxbs)
 		buflen = minbs;
 	else {
-		r = os_random_long(&td->bsrange_state);
+		if (td->o.use_os_rand)
+			r = os_random_long(&td->bsrange_state);
+		else
+			r = __rand(&td->__bsrange_state);
+
 		if (!td->o.bssplit_nr[ddir]) {
 			buflen = 1 + (unsigned int) ((double) maxbs *
-					(r / (OS_RAND_MAX + 1.0)));
+					(r / (rand_max + 1.0)));
 			if (buflen < minbs)
 				buflen = minbs;
 		} else {
@@ -361,7 +380,7 @@ static unsigned int __get_next_buflen(struct thread_data *td, struct io_u *io_u)
 
 				buflen = bsp->bs;
 				perc += bsp->perc;
-				if (r <= ((OS_RAND_MAX / 100L) * perc))
+				if (r <= ((rand_max / 100L) * perc))
 					break;
 			}
 		}
@@ -406,8 +425,14 @@ static inline enum fio_ddir get_rand_ddir(struct thread_data *td)
 	unsigned int v;
 	long r;
 
-	r = os_random_long(&td->rwmix_state);
-	v = 1 + (int) (100.0 * (r / (OS_RAND_MAX + 1.0)));
+	if (td->o.use_os_rand) {
+		r = os_random_long(&td->rwmix_state);
+		v = 1 + (int) (100.0 * (r / (OS_RAND_MAX + 1.0)));
+	} else {
+		r = __rand(&td->__rwmix_state);
+		v = 1 + (int) (100.0 * (r / (FRAND_MAX + 1.0)));
+	}
+
 	if (v <= td->o.rwmix[DDIR_READ])
 		return DDIR_READ;
 
@@ -823,11 +848,19 @@ static struct fio_file *get_next_file_rand(struct thread_data *td,
 	int fno;
 
 	do {
-		long r = os_random_long(&td->next_file_state);
 		int opened = 0;
+		long r;
+
+		if (td->o.use_os_rand) {
+			r = os_random_long(&td->next_file_state);
+			fno = (unsigned int) ((double) td->o.nr_files
+				* (r / (OS_RAND_MAX + 1.0)));
+		} else {
+			r = __rand(&td->__next_file_state);
+			fno = (unsigned int) ((double) td->o.nr_files
+				* (r / (FRAND_MAX + 1.0)));
+		}
 
-		fno = (unsigned int) ((double) td->o.nr_files
-			* (r / (OS_RAND_MAX + 1.0)));
 		f = td->files[fno];
 		if (fio_file_done(f))
 			continue;
diff --git a/lib/rand.c b/lib/rand.c
index 0681282..3b2d67a 100644
--- a/lib/rand.c
+++ b/lib/rand.c
@@ -43,20 +43,28 @@ static inline int __seed(unsigned int x, unsigned int m)
 	return (x < m) ? x + m : x;
 }
 
+static void __init_rand(struct frand_state *state, unsigned int seed)
+{
+	int cranks = 6;
+
+#define LCG(x, seed)  ((x) * 69069 ^ (seed))
+
+	state->s1 = __seed(LCG((2^31) + (2^17) + (2^7), seed), 1);
+	state->s2 = __seed(LCG(state->s1, seed), 7);
+	state->s3 = __seed(LCG(state->s2, seed), 15);
+
+	while (cranks--)
+		__rand(state);
+}
+
 void init_rand(struct frand_state *state)
 {
-#define LCG(x)  ((x) * 69069)   /* super-duper LCG */
-
-	state->s1 = __seed(LCG((2^31) + (2^17) + (2^7)), 1);
-	state->s2 = __seed(LCG(state->s1), 7);
-	state->s3 = __seed(LCG(state->s2), 15);
-
-	__rand(state);
-	__rand(state);
-	__rand(state);
-	__rand(state);
-	__rand(state);
-	__rand(state);
+	__init_rand(state, 1);
+}
+
+void init_rand_seed(struct frand_state *state, unsigned int seed)
+{
+	__init_rand(state, seed);
 }
 
 void __fill_random_buf(void *buf, unsigned int len, unsigned long seed)
diff --git a/lib/rand.h b/lib/rand.h
index 02e6858..f80c111 100644
--- a/lib/rand.h
+++ b/lib/rand.h
@@ -1,6 +1,8 @@
 #ifndef FIO_RAND_H
 #define FIO_RAND_H
 
+#define FRAND_MAX	(-1U)
+
 struct frand_state {
 	unsigned int s1, s2, s3;
 };
@@ -19,6 +21,7 @@ static inline unsigned int __rand(struct frand_state *state)
 }
 
 extern void init_rand(struct frand_state *);
+extern void init_rand_seed(struct frand_state *, unsigned int seed);
 extern void __fill_random_buf(void *buf, unsigned int len, unsigned long seed);
 extern unsigned long fill_random_buf(void *buf, unsigned int len);
 
diff --git a/options.c b/options.c
index 55d11ae..28a17cf 100644
--- a/options.c
+++ b/options.c
@@ -1116,6 +1116,14 @@ static struct fio_option options[FIO_MAX_OPTS] = {
 		.parent = "rw",
 	},
 	{
+		.name	= "use_os_rand",
+		.type	= FIO_OPT_BOOL,
+		.off1	= td_var_offset(use_os_rand),
+		.help	= "Set to use OS random generator",
+		.def	= "0",
+		.parent = "rw",
+	},
+	{
 		.name	= "norandommap",
 		.type	= FIO_OPT_STR_SET,
 		.off1	= td_var_offset(norandommap),
diff --git a/trim.c b/trim.c
index 3da1e74..a9b15d6 100644
--- a/trim.c
+++ b/trim.c
@@ -75,10 +75,15 @@ int io_u_should_trim(struct thread_data *td, struct io_u *io_u)
 	if (!td->o.trim_percentage)
 		return 0;
 
-	r = os_random_long(&td->trim_state);
-	val = (OS_RAND_MAX / 100ULL);
-	val *= (unsigned long long) td->o.trim_percentage;
+	if (td->o.use_os_rand) {
+		r = os_random_long(&td->trim_state);
+		val = (OS_RAND_MAX / 100ULL);
+	} else {
+		r = __rand(&td->__trim_state);
+		val = (FRAND_MAX / 100ULL);
+	}
 
+	val *= (unsigned long long) td->o.trim_percentage;
 	return r <= val;
 }
 #endif
--
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