Improve rate limiting
authorJens Axboe <axboe@fb.com>
Thu, 15 Jan 2015 17:39:12 +0000 (10:39 -0700)
committerJens Axboe <axboe@fb.com>
Thu, 15 Jan 2015 17:39:12 +0000 (10:39 -0700)
If we have pending IO, we should commit it before going to sleep,
not just wait for IO that has already been issued.

Also improve the delay functions to return the time spent, so
that users don't have to track tha separately if they care about
the precision.

Signed-off-by: Jens Axboe <axboe@fb.com>
fio_time.h
io_u.c
time.c

index 27520b05912260a40b2f7ccdf84a24d87650e211..79f324a330506a9c2e54aadebc7d97df0974f224 100644 (file)
@@ -10,8 +10,8 @@ extern uint64_t time_since_now(const struct timeval *);
 extern uint64_t time_since_genesis(void);
 extern uint64_t mtime_since_genesis(void);
 extern uint64_t utime_since_genesis(void);
 extern uint64_t time_since_genesis(void);
 extern uint64_t mtime_since_genesis(void);
 extern uint64_t utime_since_genesis(void);
-extern void usec_spin(unsigned int);
-extern void usec_sleep(struct thread_data *, unsigned long);
+extern uint64_t usec_spin(unsigned int);
+extern uint64_t usec_sleep(struct thread_data *, unsigned long);
 extern void fill_start_time(struct timeval *);
 extern void set_genesis_time(void);
 extern int ramp_time_over(struct thread_data *);
 extern void fill_start_time(struct timeval *);
 extern void set_genesis_time(void);
 extern int ramp_time_over(struct thread_data *);
diff --git a/io_u.c b/io_u.c
index 23a9e4ada729efbc2a53bd9b3d4e12047be1d5c6..5971d78b635e6d31c352f187042cc238c0fd7428 100644 (file)
--- a/io_u.c
+++ b/io_u.c
@@ -529,6 +529,12 @@ void io_u_quiesce(struct thread_data *td)
         * io's that have been actually submitted to an async engine,
         * and cur_depth is meaningless for sync engines.
         */
         * io's that have been actually submitted to an async engine,
         * and cur_depth is meaningless for sync engines.
         */
+       if (td->io_u_queued || td->cur_depth) {
+               int fio_unused ret;
+
+               ret = td_io_commit(td);
+       }
+
        while (td->io_u_in_flight) {
                int fio_unused ret;
 
        while (td->io_u_in_flight) {
                int fio_unused ret;
 
@@ -539,7 +545,6 @@ void io_u_quiesce(struct thread_data *td)
 static enum fio_ddir rate_ddir(struct thread_data *td, enum fio_ddir ddir)
 {
        enum fio_ddir odir = ddir ^ 1;
 static enum fio_ddir rate_ddir(struct thread_data *td, enum fio_ddir ddir)
 {
        enum fio_ddir odir = ddir ^ 1;
-       struct timeval t;
        long usec;
 
        assert(ddir_rw(ddir));
        long usec;
 
        assert(ddir_rw(ddir));
@@ -574,9 +579,7 @@ static enum fio_ddir rate_ddir(struct thread_data *td, enum fio_ddir ddir)
 
        io_u_quiesce(td);
 
 
        io_u_quiesce(td);
 
-       fio_gettime(&t, NULL);
-       usec_sleep(td, usec);
-       usec = utime_since_now(&t);
+       usec = usec_sleep(td, usec);
 
        td->rate_pending_usleep[ddir] -= usec;
 
 
        td->rate_pending_usleep[ddir] -= usec;
 
diff --git a/time.c b/time.c
index b145dc5b639a3d2bea37b6cae4c528cfdc17cf97..f1833c7b9ea42d368c06eda180528d68db8e3c2c 100644 (file)
--- a/time.c
+++ b/time.c
@@ -9,25 +9,29 @@ static unsigned long ns_granularity;
 /*
  * busy looping version for the last few usec
  */
 /*
  * busy looping version for the last few usec
  */
-void usec_spin(unsigned int usec)
+uint64_t usec_spin(unsigned int usec)
 {
        struct timeval start;
 {
        struct timeval start;
+       uint64_t t;
 
        fio_gettime(&start, NULL);
 
        fio_gettime(&start, NULL);
-       while (utime_since_now(&start) < usec)
+       while ((t = utime_since_now(&start)) < usec)
                nop;
                nop;
+
+       return t;
 }
 
 }
 
-void usec_sleep(struct thread_data *td, unsigned long usec)
+uint64_t usec_sleep(struct thread_data *td, unsigned long usec)
 {
        struct timespec req;
        struct timeval tv;
 {
        struct timespec req;
        struct timeval tv;
+       uint64_t t = 0;
 
        do {
                unsigned long ts = usec;
 
                if (usec < ns_granularity) {
 
        do {
                unsigned long ts = usec;
 
                if (usec < ns_granularity) {
-                       usec_spin(usec);
+                       t += usec_spin(usec);
                        break;
                }
 
                        break;
                }
 
@@ -46,11 +50,14 @@ void usec_sleep(struct thread_data *td, unsigned long usec)
                        break;
 
                ts = utime_since_now(&tv);
                        break;
 
                ts = utime_since_now(&tv);
+               t += ts;
                if (ts >= usec)
                        break;
 
                usec -= ts;
        } while (!td->terminate);
                if (ts >= usec)
                        break;
 
                usec -= ts;
        } while (!td->terminate);
+
+       return t;
 }
 
 uint64_t time_since_genesis(void)
 }
 
 uint64_t time_since_genesis(void)