Recent changes (master)
The following changes since commit 9c3e13e3314da394698ca32f21cc46d46b7cfe47:
smalloc: only clear the bitmap, not the whole pool (2015-11-07 17:33:38 -0700)
are available in the git repository at:
git://git.kernel.dk/fio.git master
for you to fetch changes up to 0127c57b82cfef26149c04b1d785897a68a6dffa:
smalloc: get rid of global lock (2015-11-09 19:38:15 -0700)
----------------------------------------------------------------
Jens Axboe (6):
Fixups for poisson rate
Add poisson rate selection to FD_RATE output Provide some consistency in rate_* options Rename rate_poisson to rate_process Clarify spread/lambda of poisson
smalloc: get rid of global lock
Song Liu (4):
Enable request flow under Poisson process
make sure __rand_0_1 does not return 0.0
add example using --rate_poisson
In fio.1 and HOWTO, add link to Poisson process in wikipedia
HOWTO | 13 +++++++-- backend.c | 22 +++++++++++++--- cconv.c | 2 ++ examples/poisson-rate-submission.fio | 14 ++++++++++ fio.1 | 44 ++++++++++++++++++------------- fio.h | 8 +++++- init.c | 2 ++ lib/rand.h | 13 +++++++++ options.c | 28 ++++++++++++++++++-- server.h | 2 +- smalloc.c | 51 +++--------------------------------- thread_options.h | 3 +++ 12 files changed, 127 insertions(+), 75 deletions(-) create mode 100644 examples/poisson-rate-submission.fio
---
Diff of recent changes:
HOWTO +11 -2
@@ -1049,7 +1049,7 @@ rate=int Cap the bandwidth used by this job. The number is in bytes/sec, will only limit writes (to 500KB/sec), the latter will only limit reads. -ratemin=int Tell fio to do whatever it can to maintain at least this +rate_min=int Tell fio to do whatever it can to maintain at least this bandwidth. Failing to meet this requirement, will cause the job to exit. The same format as rate is used for read vs write separation.
@@ -1064,6 +1064,15 @@ rate_iops_min=int If fio doesn't meet this rate of IO, it will cause the job to exit. The same format as rate is used for read vs write separation. +rate_process=str This option controls how fio manages rated IO + submissions. The default is 'linear', which submits IO in a + linear fashion with fixed delays between IOs that gets + adjusted based on IO completion rates. If this is set to + 'poisson', fio will submit IO based on a more real world + random request flow, known as the Poisson process + (https://en.wikipedia.org/wiki/Poisson_process). The lambda + will be 10^6 / IOPS for the given workload. + latency_target=int If set, fio will attempt to find the max performance point that the given workload will run at while maintaining a latency below this target. The values is given in microseconds.
@@ -1081,7 +1090,7 @@ latency_percentile=float The percentage of IOs that must fall within the max_latency=int If set, fio will exit the job if it exceeds this maximum latency. It will exit with an ETIME error. -ratecycle=int Average bandwidth for 'rate' and 'ratemin' over this number +rate_cycle=int Average bandwidth for 'rate' and 'rate_min' over this number of milliseconds. cpumask=int Set the CPU affinity of this job. The parameter given is a
backend.c +18 -4
@@ -35,6 +35,7 @@#include <sys/wait.h> #include <sys/ipc.h> #include <sys/mman.h> +#include <math.h> #include "fio.h" #ifndef FIO_NO_HAVE_SHM_H
@@ -775,17 +776,30 @@ static int io_complete_bytes_exceeded(struct thread_data *td)*/ static long long usec_for_io (struct thread_data *td,enum fio_ddir ddir) { -uint64_t secs, remainder, bps, bytes; +uint64_t secs, remainder, bps, bytes, iops;assert (!(td->flags &TD_F_CHILD )); bytes = td->rate_io_issue_bytes[ddir]; bps = td->rate_bps[ddir]; -if (bps) { + +if (td->o.rate_process ==RATE_PROCESS_POISSON ) { +uint64_t val; + iops = bps / td->o.bs[ddir]; + val = (int64_t ) (1000000 / iops) * + -logf (__rand_0_1 (&td->poisson_state)); +if (val) { +dprint (FD_RATE ,"poisson rate iops=%llu\n" , + (unsigned long long )1000000 / val); + } + td->last_usec += val; +return td->last_usec; + }else if (bps) { secs = bytes / bps; remainder = bytes % bps;return remainder *1000000 / bps + secs *1000000 ; - }else -return 0 ; + } + +return 0 ; }/*
cconv.c +2 -0
@@ -254,6 +254,7 @@ void convert_thread_options_to_cpu(struct thread_options *o, o->per_job_logs =le32_to_cpu (top->per_job_logs); o->trim_backlog =le64_to_cpu (top->trim_backlog); + o->rate_process =le32_to_cpu (top->rate_process);for (i =0 ; i <FIO_IO_U_LIST_MAX_LEN ; i++) o->percentile_list[i].u.f =fio_uint64_to_double (le64_to_cpu (top->percentile_list[i].u.i));
@@ -474,6 +475,7 @@ void convert_thread_options_to_net(struct thread_options_pack *top, top->trim_backlog =__cpu_to_le64 (o->trim_backlog); top->offset_increment =__cpu_to_le64 (o->offset_increment); top->number_ios =__cpu_to_le64 (o->number_ios); + top->rate_process =cpu_to_le32 (o->rate_process);for (i =0 ; i <FIO_IO_U_LIST_MAX_LEN ; i++) top->percentile_list[i].u.i =__cpu_to_le64 (fio_double_to_uint64 (o->percentile_list[i].u.f));
examples/poisson-rate-submission.fio new file +14 -0
@@ -0,0 +1,14 @@ +[poisson-rate-submit] +size=128m +rw=randread +ioengine=libaio +iodepth=32 +direct=1 +# by setting the submit mode to offload, we can guarantee a fixed rate of +# submission regardless of what the device completion rate is. +io_submit_mode=offload +rate_iops=50 +# Real world random request flow follows Poisson process. To give better +# insight on latency distribution, we simulate request flow under Poisson +# process. +rate_process=poisson
fio.1 +26 -18
119 lines not on this page · raw message
fio.h +7 -1
@@ -95,12 +95,16 @@ enum {FIO_RAND_SEQ_RAND_TRIM_OFF ,FIO_RAND_START_DELAY ,FIO_DEDUPE_OFF , +FIO_RAND_POISSON_OFF , FIO_RAND_NR_OFFS, };enum {IO_MODE_INLINE =0 , -IO_MODE_OFFLOAD , +IO_MODE_OFFLOAD =1 , + +RATE_PROCESS_LINEAR =0 , +RATE_PROCESS_POISSON =1 , };/*
@@ -243,6 +247,8 @@ struct thread_data {unsigned long rate_blocks[DDIR_RWDIR_CNT ];unsigned long rate_io_issue_bytes[DDIR_RWDIR_CNT ];struct timeval lastrate[DDIR_RWDIR_CNT ]; +int64_t last_usec; +struct frand_state poisson_state;/* * Enforced rate submission/completion workqueue
init.c +2 -0
@@ -473,6 +473,7 @@ static int __setup_rate(struct thread_data *td, enum fio_ddir ddir) td->rate_next_io_time[ddir] =0 ; td->rate_io_issue_bytes[ddir] =0 ; + td->last_usec =0 ;return 0 ; }
@@ -857,6 +858,7 @@ static void td_fill_rand_seeds_internal(struct thread_data *td, int use64)init_rand_seed (&td->file_size_state, td->rand_seeds[FIO_RAND_FILE_SIZE_OFF ], use64);init_rand_seed (&td->trim_state, td->rand_seeds[FIO_RAND_TRIM_OFF ], use64);init_rand_seed (&td->delay_state, td->rand_seeds[FIO_RAND_START_DELAY ], use64); +init_rand_seed (&td->poisson_state, td->rand_seeds[FIO_RAND_POISSON_OFF ],0 );if (!td_random (td))return ;
lib/rand.h +13 -0
@@ -104,6 +104,19 @@ static inline uint64_t __rand(struct frand_state *state)return __rand32 (&state->state32); } +static inline double __rand_0_1 (struct frand_state *state) +{ +if (state->use64) { +uint64_t val =__rand64 (&state->state64); + +return (val +1.0 ) / (FRAND64_MAX +1.0 ); + }else { +uint32_t val =__rand32 (&state->state32); + +return (val +1.0 ) / (FRAND32_MAX +1.0 ); + } +} +extern void init_rand (struct frand_state *,int );extern void init_rand_seed (struct frand_state *,unsigned int seed,int );extern void __fill_random_buf (void *buf,unsigned int len,unsigned long seed);
options.c +26 -2
@@ -2818,7 +2818,8 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .group = FIO_OPT_G_RATE, }, { - .name = "ratemin", + .name = "rate_min", + .alias = "ratemin", .lname = "I/O min rate", .type = FIO_OPT_INT, .off1 = td_var_offset(ratemin[DDIR_READ]),
@@ -2856,7 +2857,30 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .group = FIO_OPT_G_RATE, }, { - .name = "ratecycle", + .name = "rate_process", + .lname = "Rate Process", + .type = FIO_OPT_STR, + .off1 = td_var_offset(rate_process), + .help = "What process controls how rated IO is managed", + .def = "linear", + .category = FIO_OPT_C_IO, + .group = FIO_OPT_G_RATE, + .posval = { + { .ival = "linear", + .oval = RATE_PROCESS_LINEAR, + .help = "Linear rate of IO", + }, + { + .ival = "poisson", + .oval = RATE_PROCESS_POISSON, + .help = "Rate follows Poisson process", + }, + }, + .parent = "rate", + }, + { + .name = "rate_cycle", + .alias = "ratecycle", .lname = "I/O rate cycle", .type = FIO_OPT_INT, .off1 = td_var_offset(ratecycle),
server.h +1 -1
@@ -38,7 +38,7 @@ struct fio_net_cmd_reply { };enum { -FIO_SERVER_VER =47 , +FIO_SERVER_VER =48 ,FIO_SERVER_MAX_FRAGMENT_PDU =1024 ,FIO_SERVER_MAX_CMD_MB =2048 ,
smalloc.c +4 -47
121 lines not on this page · raw message
thread_options.h +3 -0
@@ -231,6 +231,7 @@ struct thread_options {unsigned int io_submit_mode;unsigned int rate_iops[DDIR_RWDIR_CNT ];unsigned int rate_iops_min[DDIR_RWDIR_CNT ]; +unsigned int rate_process;char *ioscheduler;
@@ -471,6 +472,8 @@ struct thread_options_pack {uint32_t io_submit_mode;uint32_t rate_iops[DDIR_RWDIR_CNT ];uint32_t rate_iops_min[DDIR_RWDIR_CNT ]; +uint32_t rate_process; +uint32_t padding_0;/* for alignment assert */ uint8_t ioscheduler[FIO_TOP_STR_MAX ];