lib/lfsr.c gettime-thread.c helpers.c lib/flist_sort.c \
lib/hweight.c lib/getrusage.c idletime.c td_error.c \
profiles/tiobench.c profiles/act.c io_u_queue.c filelock.c \
- lib/tp.c lib/bloom.c
+ lib/tp.c lib/bloom.c lib/gauss.c
ifdef CONFIG_LIBHDFS
HDFSFLAGS= -I $(JAVA_HOME)/include -I $(JAVA_HOME)/include/linux -I $(FIO_LIBHDFS_INCLUDE)
o->fsync_on_close = le32_to_cpu(top->fsync_on_close);
o->bs_is_seq_rand = le32_to_cpu(top->bs_is_seq_rand);
o->random_distribution = le32_to_cpu(top->random_distribution);
+ o->gauss_dev = le32_to_cpu(top->gauss_dev);
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);
top->fsync_on_close = cpu_to_le32(o->fsync_on_close);
top->bs_is_seq_rand = cpu_to_le32(o->bs_is_seq_rand);
top->random_distribution = cpu_to_le32(o->random_distribution);
+ top->gauss_dev = cpu_to_le32(o->gauss_dev);
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);
#include "lib/zipf.h"
#include "lib/axmap.h"
#include "lib/lfsr.h"
+#include "lib/gauss.h"
/*
* The type of object we are working on
/*
* Used for zipf random distribution
*/
- struct zipf_state zipf;
+ union {
+ struct zipf_state zipf;
+ struct gauss_state gauss;
+ };
int references;
enum fio_file_flags flags;
if (td->o.random_distribution == FIO_RAND_DIST_ZIPF)
zipf_init(&f->zipf, nranges, td->o.zipf_theta.u.f, seed);
- else
+ else if (td->o.random_distribution == FIO_RAND_DIST_PARETO)
pareto_init(&f->zipf, nranges, td->o.pareto_h.u.f, seed);
+ else if (td->o.random_distribution == FIO_RAND_DIST_GAUSS)
+ gauss_init(&f->gauss, nranges, td->o.gauss_dev, seed);
return 1;
}
FIO_RAND_DIST_RANDOM = 0,
FIO_RAND_DIST_ZIPF,
FIO_RAND_DIST_PARETO,
+ FIO_RAND_DIST_GAUSS,
};
#define FIO_DEF_ZIPF 1.1
return 0;
}
+static int __get_next_rand_offset_gauss(struct thread_data *td,
+ struct fio_file *f, enum fio_ddir ddir,
+ uint64_t *b)
+{
+ *b = gauss_next(&f->gauss);
+ return 0;
+}
+
+
static int flist_cmp(void *data, struct flist_head *a, struct flist_head *b)
{
struct rand_off *r1 = flist_entry(a, struct rand_off, list);
return __get_next_rand_offset_zipf(td, f, ddir, b);
else if (td->o.random_distribution == FIO_RAND_DIST_PARETO)
return __get_next_rand_offset_pareto(td, f, ddir, b);
+ else if (td->o.random_distribution == FIO_RAND_DIST_GAUSS)
+ return __get_next_rand_offset_gauss(td, f, ddir, b);
log_err("fio: unknown random distribution: %d\n", td->o.random_distribution);
return 1;
--- /dev/null
+#include <math.h>
+#include <string.h>
+#include <stdio.h>
+#include "../hash.h"
+#include "gauss.h"
+
+#define GAUSS_ITERS 12
+
+static int gauss_dev(struct gauss_state *gs)
+{
+ unsigned int r;
+ int vr;
+
+ if (!gs->stddev)
+ return 0;
+
+ r = __rand(&gs->r);
+ vr = gs->stddev * (r / (FRAND_MAX + 1.0));
+
+ return vr - gs->stddev / 2;
+}
+
+unsigned long long gauss_next(struct gauss_state *gs)
+{
+ unsigned long long sum = 0;
+ int i;
+
+ for (i = 0; i < GAUSS_ITERS; i++)
+ sum += __rand(&gs->r) % (gs->nranges + 1);
+
+ sum = (sum + GAUSS_ITERS - 1) / GAUSS_ITERS;
+
+ if (gs->stddev) {
+ int dev = gauss_dev(gs);
+
+ while (dev + sum >= gs->nranges)
+ dev /= 2;
+ sum += dev;
+ }
+
+ return __hash_u64(sum) % gs->nranges;
+}
+
+void gauss_init(struct gauss_state *gs, unsigned long nranges, unsigned int d,
+ unsigned int seed)
+{
+ memset(gs, 0, sizeof(*gs));
+ init_rand_seed(&gs->r, seed);
+ gs->nranges = nranges;
+ gs->stddev = d;
+ if (gs->stddev > nranges / 2)
+ gs->stddev = nranges / 2;
+}
--- /dev/null
+#ifndef FIO_GAUSS_H
+#define FIO_GAUSS_H
+
+#include <inttypes.h>
+#include "rand.h"
+
+struct gauss_state {
+ struct frand_state r;
+ uint64_t nranges;
+ unsigned int stddev;
+};
+
+void gauss_init(struct gauss_state *gs, unsigned long nranges, unsigned int d,
+ unsigned int seed);
+unsigned long long gauss_next(struct gauss_state *gs);
+
+#endif
val = FIO_DEF_ZIPF;
else if (td->o.random_distribution == FIO_RAND_DIST_PARETO)
val = FIO_DEF_PARETO;
+ else if (td->o.random_distribution == FIO_RAND_DIST_GAUSS)
+ val = 0.0;
else
return 0;
return 1;
}
td->o.zipf_theta.u.f = val;
- } else {
+ } else if (td->o.random_distribution == FIO_RAND_DIST_PARETO) {
if (val <= 0.00 || val >= 1.00) {
log_err("fio: pareto input out of range (0 < input < 1.0)\n");
return 1;
}
td->o.pareto_h.u.f = val;
- }
+ } else
+ td->o.gauss_dev = val;
return 0;
}
.oval = FIO_RAND_DIST_PARETO,
.help = "Pareto distribution",
},
+ { .ival = "normal",
+ .oval = FIO_RAND_DIST_GAUSS,
+ .help = "Normal (gaussian) distribution",
+ },
},
.category = FIO_OPT_C_IO,
.group = FIO_OPT_G_RANDOM,
unsigned int verify_only;
unsigned int random_distribution;
+ unsigned int gauss_dev;
fio_fp64_t zipf_theta;
fio_fp64_t pareto_h;
uint32_t bs_is_seq_rand;
uint32_t random_distribution;
- uint32_t pad;
+ uint32_t gauss_dev;
fio_fp64_t zipf_theta;
fio_fp64_t pareto_h;