Enable request flow under Poisson process
authorSong Liu <songliubraving@fb.com>
Mon, 9 Nov 2015 19:34:56 +0000 (12:34 -0700)
committerJens Axboe <axboe@fb.com>
Mon, 9 Nov 2015 19:56:44 +0000 (12:56 -0700)
To better mimic real world wordload, where incoming requests follow
Poisson process, this patch enables poisson process request flow
for rate limited benchmarks.

Signed-off-by: Jens Axboe <axboe@fb.com>
backend.c
fio.1
fio.h
init.c
options.c
thread_options.h

index 0a42da3ec440673d741da6ce56e235e997caf1b6..7a030ebbbe40e2f3a10347376d1dd26eb045479c 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -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,12 +776,18 @@ 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.poisson_request) {
+               iops = bps / td->o.bs[ddir];
+               td->last_usec += (long long)(1000000 / iops) *
+                       (-logf(((float)rand() + 1) / ((float)RAND_MAX + 1)));
+               return td->last_usec;
+       } else if (bps) {
                secs = bytes / bps;
                remainder = bytes % bps;
                return remainder * 1000000 / bps + secs * 1000000;
diff --git a/fio.1 b/fio.1
index 140c9bb5356be7f5fc51dfbb040fd01207ef354e..2ecc3d3300f389dc37ab0193005d3e5f899abf3f 100644 (file)
--- a/fio.1
+++ b/fio.1
@@ -288,7 +288,7 @@ Random trim (Linux block devices only).
 .B rw, readwrite
 Mixed sequential reads and writes.
 .TP
-.B randrw 
+.B randrw
 Mixed random reads and writes.
 .TP
 .B trimwrite
@@ -658,8 +658,8 @@ IO engine that does regular EXT4_IOC_MOVE_EXT ioctls to simulate defragment acti
 request to DDIR_WRITE event
 .TP
 .B rbd
-IO engine supporting direct access to Ceph Rados Block Devices (RBD) via librbd 
-without the need to use the kernel rbd driver. This ioengine defines engine specific 
+IO engine supporting direct access to Ceph Rados Block Devices (RBD) via librbd
+without the need to use the kernel rbd driver. This ioengine defines engine specific
 options.
 .TP
 .B gfapi
@@ -750,7 +750,7 @@ we simply do polling.
 .TP
 .BI iodepth_low \fR=\fPint
 Low watermark indicating when to start filling the queue again.  Default:
-\fBiodepth\fR. 
+\fBiodepth\fR.
 .TP
 .BI io_submit_mode \fR=\fPstr
 This option controls how fio submits the IO to the IO engine. The default is
@@ -963,6 +963,10 @@ size is used as the metric.
 If this rate of I/O is not met, the job will exit. The same format as \fBrate\fR
 is used for read vs write separation.
 .TP
+.BI poisson \fR=\fPbool
+When rate limited, try simulate request flow under Poisson process (instead
+of even distribution). Default: false.
+.TP
 .BI ratecycle \fR=\fPint
 Average bandwidth for \fBrate\fR and \fBratemin\fR over this number of
 milliseconds.  Default: 1000ms.
@@ -1280,8 +1284,8 @@ only N blocks before verifying these blocks.
 .BI verify_backlog_batch \fR=\fPint
 Control how many blocks fio will verify if verify_backlog is set. If not set,
 will default to the value of \fBverify_backlog\fR (meaning the entire queue is
-read back and verified).  If \fBverify_backlog_batch\fR is less than 
-\fBverify_backlog\fR then not all blocks will be verified,  if 
+read back and verified).  If \fBverify_backlog_batch\fR is less than
+\fBverify_backlog\fR then not all blocks will be verified,  if
 \fBverify_backlog_batch\fR is larger than \fBverify_backlog\fR,  some blocks
 will be verified more than once.
 .TP
@@ -1320,7 +1324,7 @@ Start a new reporting group.  If not given, all jobs in a file will be part
 of the same reporting group, unless separated by a stonewall.
 .TP
 .BI numjobs \fR=\fPint
-Number of clones (processes/threads performing the same workload) of this job.  
+Number of clones (processes/threads performing the same workload) of this job.
 Default: 1.
 .TP
 .B group_reporting
@@ -1513,8 +1517,8 @@ errors for given error type is separated with ':'.
 Error may be symbol ('ENOSPC', 'ENOMEM') or an integer.
 .br
 Example: ignore_error=EAGAIN,ENOSPC:122 .
-.br    
-This option will ignore EAGAIN from READ, and ENOSPC and 122(EDQUOT) from WRITE. 
+.br
+This option will ignore EAGAIN from READ, and ENOSPC and 122(EDQUOT) from WRITE.
 .TP
 .BI error_dump \fR=\fPbool
 If set dump every error even if it is non fatal, true by default. If disabled
@@ -1687,7 +1691,7 @@ Set the TCP maximum segment size (TCP_MAXSEG).
 File will be used as a block donor (swap extents between files)
 .TP
 .BI (e4defrag,inplace) \fR=\fPint
-Configure donor file block allocation strategy         
+Configure donor file block allocation strategy
 .RS
 .BI 0(default) :
 Preallocate donor's file on init
@@ -1951,7 +1955,7 @@ Disk utilization (1 for each disk used):
 .P
 Error Info (dependent on continue_on_error, default off):
 .RS
-.B total # errors, first error code 
+.B total # errors, first error code
 .RE
 .P
 .B text description (if provided in config - appears on newline)
@@ -2018,7 +2022,7 @@ fio \-\-client=server \-\-remote-config /path/to/file.fio
 Then fio will open this local (to the server) job file instead
 of being passed one from the client.
 
-If you have many servers (example: 100 VMs/containers), you can input a pathname 
+If you have many servers (example: 100 VMs/containers), you can input a pathname
 of a file containing host IPs/names as the parameter value for the \-\-client option.
 For example, here is an example "host.list" file containing 2 hostnames:
 
@@ -2034,8 +2038,8 @@ In this mode, you cannot input server-specific parameters or job files, and all
 servers receive the same job file.
 
 In order to enable fio \-\-client runs utilizing a shared filesystem from multiple hosts,
-fio \-\-client now prepends the IP address of the server to the filename. For example, 
-if fio is using directory /mnt/nfs/fio and is writing filename fileio.tmp, 
+fio \-\-client now prepends the IP address of the server to the filename. For example,
+if fio is using directory /mnt/nfs/fio and is writing filename fileio.tmp,
 with a \-\-client hostfile
 containing two hostnames h1 and h2 with IP addresses 192.168.10.120 and 192.168.10.121, then
 fio will create two files:
@@ -2059,4 +2063,3 @@ See \fBREADME\fR.
 For further documentation see \fBHOWTO\fR and \fBREADME\fR.
 .br
 Sample jobfiles are available in the \fBexamples\fR directory.
-
diff --git a/fio.h b/fio.h
index 5e8ac66686d30753519139f80903a4f3a11281d9..6bb1949f9faed23d2d8977ed3df3f2db32dfd4ab 100644 (file)
--- a/fio.h
+++ b/fio.h
@@ -243,6 +243,7 @@ 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];
+       unsigned long long last_usec;
 
        /*
         * Enforced rate submission/completion workqueue
diff --git a/init.c b/init.c
index e09872f0367940c686392e296107ff11006fd4f5..242518ccd703f426eb216f86c9e5718da5138df2 100644 (file)
--- a/init.c
+++ b/init.c
@@ -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;
 }
 
index 55844130fae135793cb7619063c9f668993bf9e3..8198e6b424a631e466ce680beaa8b931a2d2480a 100644 (file)
--- a/options.c
+++ b/options.c
@@ -2855,6 +2855,17 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .category = FIO_OPT_C_IO,
                .group  = FIO_OPT_G_RATE,
        },
+       {
+               .name   = "poisson",
+               .lname  = "simulate requests under Poisson process",
+               .type   = FIO_OPT_BOOL,
+               .off1   = td_var_offset(poisson_request),
+               .help   = "with rate limit, try simulate requests that follow Poisson process",
+               .def    = "0",
+               .hide   = 1,
+               .category = FIO_OPT_C_IO,
+               .group  = FIO_OPT_G_RATE,
+       },
        {
                .name   = "ratecycle",
                .lname  = "I/O rate cycle",
index ed960eeb2861de263d3ac036d3e55483ab008396..4c26dcb53ff759a6b9d7a06e75525dbc0c6e70aa 100644 (file)
@@ -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 poisson_request;
 
        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 poisson_request;
+       uint32_t padding_0;   /* for alignment assert */
 
        uint8_t ioscheduler[FIO_TOP_STR_MAX];