random_distribution=zipf:1.2 as the option. If a non-uniform
model is used, fio will disable use of the random map.
+percentage_random=int For a random workload, set how big a percentage should
+ be random. This defaults to 100%, in which case the workload
+ is fully random. It can be set from anywhere from 0 to 100.
+ Setting it to 0 would make the workload fully sequential. Any
+ setting in between will result in a random mix of sequential
+ and random IO, at the given percentages.
+
+percentage_sequential=int See percentage_random. It is guaranteed that
+ they add up to 100. The later setting has priority, each
+ will adjust the other.
+
norandommap Normally fio will cover every block of the file when doing
random IO. If this option is given, fio will just get a
new random offset without looking at past io history. This
o->zipf_theta.u.f = fio_uint64_to_double(le64_to_cpu(top->zipf_theta.u.i));
o->pareto_h.u.f = fio_uint64_to_double(le64_to_cpu(top->pareto_h.u.i));
o->random_generator = le32_to_cpu(top->random_generator);
+ o->perc_rand = le32_to_cpu(top->perc_rand);
+ o->perc_seq = le32_to_cpu(top->perc_seq);
o->hugepage_size = le32_to_cpu(top->hugepage_size);
o->rw_min_bs = le32_to_cpu(top->rw_min_bs);
o->thinktime = le32_to_cpu(top->thinktime);
top->zipf_theta.u.i = __cpu_to_le64(fio_double_to_uint64(o->zipf_theta.u.f));
top->pareto_h.u.i = __cpu_to_le64(fio_double_to_uint64(o->pareto_h.u.f));
top->random_generator = cpu_to_le32(o->random_generator);
+ top->perc_rand = cpu_to_le32(o->perc_rand);
+ top->perc_seq = cpu_to_le32(o->perc_seq);
top->hugepage_size = cpu_to_le32(o->hugepage_size);
top->rw_min_bs = cpu_to_le32(o->rw_min_bs);
top->thinktime = cpu_to_le32(o->thinktime);
random_distribution=zipf:1.2 as the option. If a non-uniform model is used,
fio will disable use of the random map.
.TP
+.BI percentage_random \fR=\fPint
+For a random workload, set how big a percentage should be random. This defaults
+to 100%, in which case the workload is fully random. It can be set from
+anywhere from 0 to 100. Setting it to 0 would make the workload fully
+sequential.
+.TP
+.BI percentage_sequential \fR=\fPint
+See \fBpercentage_random\fR.
+.TP
.B norandommap
Normally \fBfio\fR will cover every block of the file when doing random I/O. If
this parameter is given, a new offset will be chosen without looking at past
FIO_RAND_FILE_SIZE_OFF,
FIO_RAND_TRIM_OFF,
FIO_RAND_BUF_OFF,
+ FIO_RAND_SEQ_RAND_OFF,
FIO_RAND_NR_OFFS,
};
enum fio_ddir rwmix_ddir;
unsigned int ddir_seq_nr;
+ /*
+ * rand/seq mixed workload state
+ */
+ union {
+ os_random_state_t seq_rand_state;
+ struct frand_state __seq_rand_state;
+ };
+
/*
* IO history logs for verification. We use a tree for sorting,
* if we are overwriting. Otherwise just use a fifo.
td->rand_seeds[FIO_RAND_BLOCK_OFF] = FIO_RANDSEED * td->thread_number;
os_random_seed(td->rand_seeds[FIO_RAND_BLOCK_OFF], &td->random_state);
+ os_random_seed(td->rand_seeds[FIO_RAND_SEQ_RAND_OFF], &td->seq_rand_state);
}
static void td_fill_rand_seeds_internal(struct thread_data *td)
td->rand_seeds[FIO_RAND_BLOCK_OFF] = FIO_RANDSEED * td->thread_number;
init_rand_seed(&td->__random_state, td->rand_seeds[FIO_RAND_BLOCK_OFF]);
+ init_rand_seed(&td->__seq_rand_state, td->rand_seeds[FIO_RAND_SEQ_RAND_OFF]);
}
void td_fill_rand_seeds(struct thread_data *td)
return 1;
}
+static int should_do_random(struct thread_data *td)
+{
+ unsigned int v;
+ unsigned long r;
+
+ if (td->o.perc_rand == 100)
+ return 1;
+
+ if (td->o.use_os_rand) {
+ r = os_random_long(&td->seq_rand_state);
+ v = 1 + (int) (100.0 * (r / (OS_RAND_MAX + 1.0)));
+ } else {
+ r = __rand(&td->__seq_rand_state);
+ v = 1 + (int) (100.0 * (r / (FRAND_MAX + 1.0)));
+ }
+
+ return v <= td->o.perc_rand;
+}
+
static int get_next_rand_offset(struct thread_data *td, struct fio_file *f,
enum fio_ddir ddir, uint64_t *b)
{
b = offset = -1ULL;
if (rw_seq) {
- if (td_random(td))
- ret = get_next_rand_block(td, f, ddir, &b);
- else
+ if (td_random(td)) {
+ if (should_do_random(td))
+ ret = get_next_rand_block(td, f, ddir, &b);
+ else {
+ io_u->flags |= IO_U_F_BUSY_OK;
+ ret = get_next_seq_offset(td, f, ddir, &offset);
+ if (ret)
+ ret = get_next_rand_block(td, f, ddir, &b);
+ }
+ } else
ret = get_next_seq_offset(td, f, ddir, &offset);
} else {
io_u->flags |= IO_U_F_BUSY_OK;
return 0;
}
+static int str_perc_rand_cb(void *data, unsigned long long *val)
+{
+ struct thread_data *td = data;
+
+ td->o.perc_rand = *val;
+ td->o.perc_seq = 100 - *val;
+ return 0;
+}
+
+static int str_perc_seq_cb(void *data, unsigned long long *val)
+{
+ struct thread_data *td = data;
+
+ td->o.perc_seq = *val;
+ td->o.perc_rand = 100 - *val;
+ return 0;
+}
+
+
static int str_exitall_cb(void)
{
exitall_on_terminate = 1;
.category = FIO_OPT_C_IO,
.group = FIO_OPT_G_RANDOM,
},
+ {
+ .name = "percentage_random",
+ .lname = "Percentage Random",
+ .type = FIO_OPT_INT,
+ .cb = str_perc_rand_cb,
+ .maxval = 100,
+ .help = "Percentage of seq/random mix that should be random",
+ .def = "100",
+ .interval = 5,
+ .inverse = "percentage_sequential",
+ .category = FIO_OPT_C_IO,
+ .group = FIO_OPT_G_RANDOM,
+ },
+ {
+ .name = "percentage_sequential",
+ .lname = "Percentage Sequential",
+ .type = FIO_OPT_INT,
+ .cb = str_perc_seq_cb,
+ .maxval = 100,
+ .help = "Percentage of seq/random mix that should be sequential",
+ .def = "0",
+ .interval = 5,
+ .inverse = "percentage_random",
+ .category = FIO_OPT_C_IO,
+ .group = FIO_OPT_G_RANDOM,
+ },
{
.name = "nrfiles",
.lname = "Number of files",
unsigned int random_generator;
+ unsigned int perc_rand;
+ unsigned int perc_seq;
+
unsigned int hugepage_size;
unsigned int rw_min_bs;
unsigned int thinktime;
uint32_t random_generator;
+ uint32_t perc_rand;
+ uint32_t perc_seq;
+
uint32_t hugepage_size;
uint32_t rw_min_bs;
uint32_t thinktime;