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
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
#include "profile.h"
#include "time.h"
#include "lib/getopt.h"
+#include "lib/rand.h"
#ifdef FIO_HAVE_GUASI
#include <guasi.h>
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;
* State for random io, a bitmap of blocks done vs not done
*/
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 */
td->rand_seeds[4] = FIO_RANDSEED * td->thread_number;
os_random_seed(td->rand_seeds[4], &td->random_state);
+ init_rand_seed(&td->__random_state, td->rand_seeds[4]);
}
/*
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.
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)
#ifndef FIO_RAND_H
#define FIO_RAND_H
+#define FRAND_MAX (-1U)
+
struct frand_state {
unsigned int s1, s2, s3;
};
}
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);
.def = "1",
.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,