[PATCH] Split status/eta code out of fio.c
authorJens Axboe <jens.axboe@oracle.com>
Wed, 18 Oct 2006 13:37:01 +0000 (15:37 +0200)
committerJens Axboe <jens.axboe@oracle.com>
Wed, 18 Oct 2006 13:37:01 +0000 (15:37 +0200)
All in the name of making the code base easier to go through.

Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Makefile
eta.c [new file with mode: 0644]
fio.c
fio.h
time.c

index b1a498635975bf0fef363d0dd0442a4a9d5d7853..80a0397502a91f464e30895db2c26c6913f42c6b 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -15,7 +15,7 @@ CFLAGS += '-D_INST_PREFIX="$(FIO_INST_DIR)"'
 all: depend $(PROGS) $(SCRIPTS)
        $(MAKE) -C engines
 
-fio: fio.o ioengines.o init.o stat.o log.o time.o md5.o crc32.o filesetup.o
+fio: fio.o ioengines.o init.o stat.o log.o time.o md5.o crc32.o filesetup.o eta.o
        $(CC) $(CFLAGS) -o $@ $(filter %.o,$^) -lpthread -laio -lm -lrt -ldl
 
 clean:
diff --git a/eta.c b/eta.c
new file mode 100644 (file)
index 0000000..9ad0b49
--- /dev/null
+++ b/eta.c
@@ -0,0 +1,231 @@
+/*
+ * Status and ETA code
+ */
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include "fio.h"
+#include "os.h"
+
+static char run_str[MAX_JOBS + 1];
+
+/*
+ * Sets the status of the 'td' in the printed status map.
+ */
+static void check_str_update(struct thread_data *td)
+{
+       char c = run_str[td->thread_number - 1];
+
+       switch (td->runstate) {
+               case TD_REAPED:
+                       c = '_';
+                       break;
+               case TD_EXITED:
+                       c = 'E';
+                       break;
+               case TD_RUNNING:
+                       if (td_rw(td)) {
+                               if (td->sequential)
+                                       c = 'M';
+                               else
+                                       c = 'm';
+                       } else if (td_read(td)) {
+                               if (td->sequential)
+                                       c = 'R';
+                               else
+                                       c = 'r';
+                       } else {
+                               if (td->sequential)
+                                       c = 'W';
+                               else
+                                       c = 'w';
+                       }
+                       break;
+               case TD_VERIFYING:
+                       c = 'V';
+                       break;
+               case TD_FSYNCING:
+                       c = 'F';
+                       break;
+               case TD_CREATED:
+                       c = 'C';
+                       break;
+               case TD_INITIALIZED:
+                       c = 'I';
+                       break;
+               case TD_NOT_CREATED:
+                       c = 'P';
+                       break;
+               default:
+                       log_err("state %d\n", td->runstate);
+       }
+
+       run_str[td->thread_number - 1] = c;
+}
+
+/*
+ * Convert seconds to a printable string.
+ */
+static void eta_to_str(char *str, int eta_sec)
+{
+       unsigned int d, h, m, s;
+       static int always_d, always_h;
+
+       d = h = m = s = 0;
+
+       s = eta_sec % 60;
+       eta_sec /= 60;
+       m = eta_sec % 60;
+       eta_sec /= 60;
+       h = eta_sec % 24;
+       eta_sec /= 24;
+       d = eta_sec;
+
+       if (d || always_d) {
+               always_d = 1;
+               str += sprintf(str, "%02dd:", d);
+       }
+       if (h || always_h) {
+               always_h = 1;
+               str += sprintf(str, "%02dh:", h);
+       }
+
+       str += sprintf(str, "%02dm:", m);
+       str += sprintf(str, "%02ds", s);
+}
+
+/*
+ * Best effort calculation of the estimated pending runtime of a job.
+ */
+static int thread_eta(struct thread_data *td, unsigned long elapsed)
+{
+       unsigned long long bytes_total, bytes_done;
+       unsigned int eta_sec = 0;
+
+       bytes_total = td->total_io_size;
+
+       if (td->zone_size && td->zone_skip)
+               bytes_total /= (td->zone_skip / td->zone_size);
+
+       if (td->runstate == TD_RUNNING || td->runstate == TD_VERIFYING) {
+               double perc;
+
+               bytes_done = td->io_bytes[DDIR_READ] + td->io_bytes[DDIR_WRITE];
+               perc = (double) bytes_done / (double) bytes_total;
+               if (perc > 1.0)
+                       perc = 1.0;
+
+               eta_sec = (elapsed * (1.0 / perc)) - elapsed;
+
+               if (td->timeout && eta_sec > (td->timeout - elapsed))
+                       eta_sec = td->timeout - elapsed;
+       } else if (td->runstate == TD_NOT_CREATED || td->runstate == TD_CREATED
+                       || td->runstate == TD_INITIALIZED) {
+               int t_eta = 0, r_eta = 0;
+
+               /*
+                * We can only guess - assume it'll run the full timeout
+                * if given, otherwise assume it'll run at the specified rate.
+                */
+               if (td->timeout)
+                       t_eta = td->timeout + td->start_delay - elapsed;
+               if (td->rate) {
+                       r_eta = (bytes_total / 1024) / td->rate;
+                       r_eta += td->start_delay - elapsed;
+               }
+
+               if (r_eta && t_eta)
+                       eta_sec = min(r_eta, t_eta);
+               else if (r_eta)
+                       eta_sec = r_eta;
+               else if (t_eta)
+                       eta_sec = t_eta;
+               else
+                       eta_sec = 0;
+       } else {
+               /*
+                * thread is already done or waiting for fsync
+                */
+               eta_sec = 0;
+       }
+
+       return eta_sec;
+}
+
+/*
+ * Print status of the jobs we know about. This includes rate estimates,
+ * ETA, thread state, etc.
+ */
+void print_thread_status(void)
+{
+       unsigned long elapsed = mtime_since_genesis() / 1000;
+       int i, nr_running, nr_pending, t_rate, m_rate, *eta_secs, eta_sec;
+       char eta_str[32];
+       double perc = 0.0;
+
+       if (temp_stall_ts || terse_output)
+               return;
+
+       eta_secs = malloc(thread_number * sizeof(int));
+       memset(eta_secs, 0, thread_number * sizeof(int));
+
+       nr_pending = nr_running = t_rate = m_rate = 0;
+       for (i = 0; i < thread_number; i++) {
+               struct thread_data *td = &threads[i];
+
+               if (td->runstate == TD_RUNNING || td->runstate == TD_VERIFYING||
+                   td->runstate == TD_FSYNCING) {
+                       nr_running++;
+                       t_rate += td->rate;
+                       m_rate += td->ratemin;
+               } else if (td->runstate < TD_RUNNING)
+                       nr_pending++;
+
+               if (elapsed >= 3)
+                       eta_secs[i] = thread_eta(td, elapsed);
+               else
+                       eta_secs[i] = INT_MAX;
+
+               check_str_update(td);
+       }
+
+       if (exitall_on_terminate)
+               eta_sec = INT_MAX;
+       else
+               eta_sec = 0;
+
+       for (i = 0; i < thread_number; i++) {
+               if (exitall_on_terminate) {
+                       if (eta_secs[i] < eta_sec)
+                               eta_sec = eta_secs[i];
+               } else {
+                       if (eta_secs[i] > eta_sec)
+                               eta_sec = eta_secs[i];
+               }
+       }
+
+       if (eta_sec != INT_MAX && elapsed) {
+               perc = (double) elapsed / (double) (elapsed + eta_sec);
+               eta_to_str(eta_str, eta_sec);
+       }
+
+       if (!nr_running && !nr_pending)
+               return;
+
+       printf("Threads running: %d", nr_running);
+       if (m_rate || t_rate)
+               printf(", commitrate %d/%dKiB/sec", t_rate, m_rate);
+       if (eta_sec != INT_MAX && nr_running) {
+               perc *= 100.0;
+               printf(": [%s] [%3.2f%% done] [eta %s]", run_str, perc,eta_str);
+       }
+       printf("\r");
+       fflush(stdout);
+       free(eta_secs);
+}
+
+void print_status_init(int thread_number)
+{
+       run_str[thread_number] = 'P';
+}
diff --git a/fio.c b/fio.c
index 1fb35fb181534b646d8b8a3545a616c7205d598c..a146f035c19f5f18647aa2ce34a9fa1476fec3d8 100644 (file)
--- a/fio.c
+++ b/fio.c
 
 int groupid = 0;
 int thread_number = 0;
-static char run_str[MAX_JOBS + 1];
 int shm_id = 0;
-static struct timeval genesis;
 int temp_stall_ts;
 char *fio_inst_prefix = _INST_PREFIX;
 
-static void print_thread_status(void);
-
 extern unsigned long long mlock_size;
 
-/*
- * Thread life cycle. Once a thread has a runstate beyond TD_INITIALIZED, it
- * will never back again. It may cycle between running/verififying/fsyncing.
- * Once the thread reaches TD_EXITED, it is just waiting for the core to
- * reap it.
- */
-enum {
-       TD_NOT_CREATED = 0,
-       TD_CREATED,
-       TD_INITIALIZED,
-       TD_RUNNING,
-       TD_VERIFYING,
-       TD_FSYNCING,
-       TD_EXITED,
-       TD_REAPED,
-};
-
 #define should_fsync(td)       ((td_write(td) || td_rw(td)) && (!(td)->odirect || (td)->override_sync))
 
 static volatile int startup_sem;
@@ -1256,221 +1235,6 @@ static void *fork_main(int shmid, int offset)
        return NULL;
 }
 
-/*
- * Sets the status of the 'td' in the printed status map.
- */
-static void check_str_update(struct thread_data *td)
-{
-       char c = run_str[td->thread_number - 1];
-
-       switch (td->runstate) {
-               case TD_REAPED:
-                       c = '_';
-                       break;
-               case TD_EXITED:
-                       c = 'E';
-                       break;
-               case TD_RUNNING:
-                       if (td_rw(td)) {
-                               if (td->sequential)
-                                       c = 'M';
-                               else
-                                       c = 'm';
-                       } else if (td_read(td)) {
-                               if (td->sequential)
-                                       c = 'R';
-                               else
-                                       c = 'r';
-                       } else {
-                               if (td->sequential)
-                                       c = 'W';
-                               else
-                                       c = 'w';
-                       }
-                       break;
-               case TD_VERIFYING:
-                       c = 'V';
-                       break;
-               case TD_FSYNCING:
-                       c = 'F';
-                       break;
-               case TD_CREATED:
-                       c = 'C';
-                       break;
-               case TD_INITIALIZED:
-                       c = 'I';
-                       break;
-               case TD_NOT_CREATED:
-                       c = 'P';
-                       break;
-               default:
-                       log_err("state %d\n", td->runstate);
-       }
-
-       run_str[td->thread_number - 1] = c;
-}
-
-/*
- * Convert seconds to a printable string.
- */
-static void eta_to_str(char *str, int eta_sec)
-{
-       unsigned int d, h, m, s;
-       static int always_d, always_h;
-
-       d = h = m = s = 0;
-
-       s = eta_sec % 60;
-       eta_sec /= 60;
-       m = eta_sec % 60;
-       eta_sec /= 60;
-       h = eta_sec % 24;
-       eta_sec /= 24;
-       d = eta_sec;
-
-       if (d || always_d) {
-               always_d = 1;
-               str += sprintf(str, "%02dd:", d);
-       }
-       if (h || always_h) {
-               always_h = 1;
-               str += sprintf(str, "%02dh:", h);
-       }
-
-       str += sprintf(str, "%02dm:", m);
-       str += sprintf(str, "%02ds", s);
-}
-
-/*
- * Best effort calculation of the estimated pending runtime of a job.
- */
-static int thread_eta(struct thread_data *td, unsigned long elapsed)
-{
-       unsigned long long bytes_total, bytes_done;
-       unsigned int eta_sec = 0;
-
-       bytes_total = td->total_io_size;
-
-       if (td->zone_size && td->zone_skip)
-               bytes_total /= (td->zone_skip / td->zone_size);
-
-       if (td->runstate == TD_RUNNING || td->runstate == TD_VERIFYING) {
-               double perc;
-
-               bytes_done = td->io_bytes[DDIR_READ] + td->io_bytes[DDIR_WRITE];
-               perc = (double) bytes_done / (double) bytes_total;
-               if (perc > 1.0)
-                       perc = 1.0;
-
-               eta_sec = (elapsed * (1.0 / perc)) - elapsed;
-
-               if (td->timeout && eta_sec > (td->timeout - elapsed))
-                       eta_sec = td->timeout - elapsed;
-       } else if (td->runstate == TD_NOT_CREATED || td->runstate == TD_CREATED
-                       || td->runstate == TD_INITIALIZED) {
-               int t_eta = 0, r_eta = 0;
-
-               /*
-                * We can only guess - assume it'll run the full timeout
-                * if given, otherwise assume it'll run at the specified rate.
-                */
-               if (td->timeout)
-                       t_eta = td->timeout + td->start_delay - elapsed;
-               if (td->rate) {
-                       r_eta = (bytes_total / 1024) / td->rate;
-                       r_eta += td->start_delay - elapsed;
-               }
-
-               if (r_eta && t_eta)
-                       eta_sec = min(r_eta, t_eta);
-               else if (r_eta)
-                       eta_sec = r_eta;
-               else if (t_eta)
-                       eta_sec = t_eta;
-               else
-                       eta_sec = 0;
-       } else {
-               /*
-                * thread is already done or waiting for fsync
-                */
-               eta_sec = 0;
-       }
-
-       return eta_sec;
-}
-
-/*
- * Print status of the jobs we know about. This includes rate estimates,
- * ETA, thread state, etc.
- */
-static void print_thread_status(void)
-{
-       unsigned long elapsed = time_since_now(&genesis);
-       int i, nr_running, nr_pending, t_rate, m_rate, *eta_secs, eta_sec;
-       char eta_str[32];
-       double perc = 0.0;
-
-       if (temp_stall_ts || terse_output)
-               return;
-
-       eta_secs = malloc(thread_number * sizeof(int));
-       memset(eta_secs, 0, thread_number * sizeof(int));
-
-       nr_pending = nr_running = t_rate = m_rate = 0;
-       for (i = 0; i < thread_number; i++) {
-               struct thread_data *td = &threads[i];
-
-               if (td->runstate == TD_RUNNING || td->runstate == TD_VERIFYING||
-                   td->runstate == TD_FSYNCING) {
-                       nr_running++;
-                       t_rate += td->rate;
-                       m_rate += td->ratemin;
-               } else if (td->runstate < TD_RUNNING)
-                       nr_pending++;
-
-               if (elapsed >= 3)
-                       eta_secs[i] = thread_eta(td, elapsed);
-               else
-                       eta_secs[i] = INT_MAX;
-
-               check_str_update(td);
-       }
-
-       if (exitall_on_terminate)
-               eta_sec = INT_MAX;
-       else
-               eta_sec = 0;
-
-       for (i = 0; i < thread_number; i++) {
-               if (exitall_on_terminate) {
-                       if (eta_secs[i] < eta_sec)
-                               eta_sec = eta_secs[i];
-               } else {
-                       if (eta_secs[i] > eta_sec)
-                               eta_sec = eta_secs[i];
-               }
-       }
-
-       if (eta_sec != INT_MAX && elapsed) {
-               perc = (double) elapsed / (double) (elapsed + eta_sec);
-               eta_to_str(eta_str, eta_sec);
-       }
-
-       if (!nr_running && !nr_pending)
-               return;
-
-       printf("Threads running: %d", nr_running);
-       if (m_rate || t_rate)
-               printf(", commitrate %d/%dKiB/sec", t_rate, m_rate);
-       if (eta_sec != INT_MAX && nr_running) {
-               perc *= 100.0;
-               printf(": [%s] [%3.2f%% done] [eta %s]", run_str, perc,eta_str);
-       }
-       printf("\r");
-       fflush(stdout);
-       free(eta_secs);
-}
-
 /*
  * Run over the job map and reap the threads that have exited, if any.
  */
@@ -1579,7 +1343,7 @@ static void run_threads(void)
        for (i = 0; i < thread_number; i++) {
                td = &threads[i];
 
-               run_str[td->thread_number - 1] = 'P';
+               print_status_init(td->thread_number - 1);
 
                init_disk_util(td);
 
@@ -1597,7 +1361,7 @@ static void run_threads(void)
                }
        }
 
-       gettimeofday(&genesis, NULL);
+       time_init();
 
        while (todo) {
                struct thread_data *map[MAX_JOBS];
@@ -1623,7 +1387,7 @@ static void run_threads(void)
                        }
 
                        if (td->start_delay) {
-                               spent = mtime_since_now(&genesis);
+                               spent = mtime_since_genesis();
 
                                if (td->start_delay * 1000 > spent)
                                        continue;
diff --git a/fio.h b/fio.h
index c778206b4097c03d4224d6aff62f76fe68c9b3fc..9471666b02b45cf7328637841e249636247f06c1 100644 (file)
--- a/fio.h
+++ b/fio.h
@@ -427,10 +427,12 @@ extern int setup_rate(struct thread_data *);
 /*
  * Time functions
  */
+extern void time_init(void);
 extern unsigned long utime_since(struct timeval *, struct timeval *);
 extern unsigned long mtime_since(struct timeval *, struct timeval *);
 extern unsigned long mtime_since_now(struct timeval *);
 extern unsigned long time_since_now(struct timeval *);
+extern unsigned long mtime_since_genesis(void);
 extern void __usec_sleep(unsigned int);
 extern void usec_sleep(struct thread_data *, unsigned long);
 extern void rate_throttle(struct thread_data *, unsigned long, unsigned int);
@@ -447,6 +449,29 @@ extern int init_random_state(struct thread_data *);
 extern void close_files(struct thread_data *);
 extern int setup_files(struct thread_data *);
 
+/*
+ * ETA/status stuff
+ */
+extern void print_thread_status(void);
+extern void print_status_init(int);
+
+/*
+ * Thread life cycle. Once a thread has a runstate beyond TD_INITIALIZED, it
+ * will never back again. It may cycle between running/verififying/fsyncing.
+ * Once the thread reaches TD_EXITED, it is just waiting for the core to
+ * reap it.
+ */
+enum {
+       TD_NOT_CREATED = 0,
+       TD_CREATED,
+       TD_INITIALIZED,
+       TD_RUNNING,
+       TD_VERIFYING,
+       TD_FSYNCING,
+       TD_EXITED,
+       TD_REAPED,
+};
+
 /*
  * This is a pretty crappy semaphore implementation, but with the use that fio
  * has (just signalling start/go conditions), it doesn't have to be better.
diff --git a/time.c b/time.c
index c7f898be3db3a853b0328c742478c8657e41eda1..ad5ee3fe51773c9019067f593834428afad8fc9b 100644 (file)
--- a/time.c
+++ b/time.c
@@ -3,6 +3,8 @@
 
 #include "fio.h"
 
+static struct timeval genesis;
+
 unsigned long utime_since(struct timeval *s, struct timeval *e)
 {
        double sec, usec;
@@ -120,3 +122,13 @@ void rate_throttle(struct thread_data *td, unsigned long time_spent,
                td->rate_pending_usleep -= overtime;
        }
 }
+
+unsigned long mtime_since_genesis(void)
+{
+       return mtime_since_now(&genesis);
+}
+
+void time_init(void)
+{
+       gettimeofday(&genesis, NULL);
+}