bench: Introduce new progress report and intervals
authorAlex Pyrgiotis <apyrgio@grnet.gr>
Wed, 17 Jul 2013 19:19:54 +0000 (22:19 +0300)
committerFilippos Giannakos <philipgian@grnet.gr>
Thu, 18 Jul 2013 10:02:48 +0000 (13:02 +0300)
This commit renews the progress report that bench has by allowing to
report bandwidth results during benchmark.

Also, an additional functionality is that of report intervals. Report
intervals allow the user to choose exactly when progress report will be
printed.

Both of these features are documented extensively in the usage section.

xseg/peers/user/bench-utils.c
xseg/peers/user/bench-xseg.c
xseg/peers/user/bench-xseg.h

index ee30efe..584ad71 100644 (file)
@@ -166,32 +166,35 @@ static struct tm_result __separate_by_order(double num)
 static void __calculate_bw(struct bench *prefs, double iops, struct bw *bw)
 {
        bw->val = iops * prefs->bs;
-       strcpy(bw->unit, "B/s");
 
-       if (bw->val < 1024)
+       if (bw->val < 1024) {
+               strcpy(bw->unit, "B/s");
                return;
+       }
 
        bw->val = bw->val / 1024;
-       strcpy(bw->unit, "KB/s");
 
-       if (bw->val < 1024)
+       if (bw->val < 1024) {
+               strcpy(bw->unit, "KB/s");
                return;
+       }
 
        bw->val = bw->val / 1024;
-       strcpy(bw->unit, "MB/s");
 
-       if (bw->val < 1024)
+       if (bw->val < 1024) {
+               strcpy(bw->unit, "MB/s");
                return;
+       }
 
        bw->val = bw->val / 1024;
        strcpy(bw->unit, "GB/s");
 }
 
-static double __calculate_iops(struct bench *prefs, double elapsed_ns)
+static double __calculate_iops(uint64_t requests, double elapsed_ns)
 {
        /* elapsed_ns is in nanoseconds, so we convert it to seconds */
        double elapsed = elapsed_ns / pow(10,9);
-       return (prefs->status->received / elapsed);
+       return (requests / elapsed);
 }
 
 /******************************\
@@ -275,11 +278,38 @@ int read_progress(char *progress)
 {
        if (strncmp(progress, "no", MAX_ARG_LEN + 1) == 0)
                return PROGRESS_NO;
-       if (strncmp(progress, "yes", MAX_ARG_LEN + 1) == 0)
-               return PROGRESS_YES;
+       if (strncmp(progress, "req", MAX_ARG_LEN + 1) == 0)
+               return PROGRESS_REQ;
+       if (strncmp(progress, "io", MAX_ARG_LEN + 1) == 0)
+               return PROGRESS_IO;
+       if (strncmp(progress, "both", MAX_ARG_LEN + 1) == 0)
+               return PROGRESS_BOTH;
        return -1;
 }
 
+/*
+ * Read interval in percentage or raw mode and return its length (in requests)
+ * If syntax is invalid, return 0.
+ */
+uint64_t read_interval(struct bench *prefs, char *str_interval)
+{
+       char *unit = NULL;
+       uint64_t interval;
+
+       interval = strtoll(str_interval, &unit, 10);
+
+       /* If interval is raw number of requests */
+       if (!unit[0] && interval < prefs->status->max)
+               return interval;
+
+       /* If interval is percentage of max requests */
+       if (strncmp(unit, "%", MAX_ARG_LEN + 1) == 0 &&
+                       interval > 0 && interval < 100)
+               return calculate_interval(prefs, interval);
+
+       return 0;
+}
+
 int read_ping(char *ping)
 {
        if (strncmp(ping, "no", MAX_ARG_LEN + 1) == 0)
@@ -309,38 +339,71 @@ int validate_seed(struct bench *prefs, unsigned long seed)
  * Print functions *
 \*******************/
 
-void clear_lines(struct bench *prefs)
+uint64_t calculate_interval(struct bench *prefs, uint64_t percentage)
 {
-       int lines = 6;
+       uint64_t interval = round((double)prefs->status->max *
+                       (double)percentage / 100);
 
-       if ((prefs->op == X_READ) &&
-                       (GET_FLAG(VERIFY, prefs->flags) != VERIFY_NO))
-               lines++;
+       if (!interval)
+               interval = 1;
 
-       /* TODO: Add bandwidth */
+       return interval;
+}
+
+int calculate_report_lines(struct bench *prefs)
+{
+       int progress = GET_FLAG(PROGRESS, prefs->flags);
+       int lines = 0;
+
+       if (progress == PROGRESS_REQ || progress == PROGRESS_BOTH) {
+               lines = 6;
+               if ((GET_FLAG(VERIFY, prefs->flags) != VERIFY_NO) &&
+                               (prefs->op == X_READ))
+                       lines++;
+       }
+       if (progress == PROGRESS_IO ||  progress == PROGRESS_BOTH) {
+               lines += 1;
+               if (prefs->op == X_READ || prefs->op == X_WRITE)
+                       lines++;
+       }
+
+       return lines;
+}
 
+void clear_report_lines(int lines)
+{
        fprintf(stdout, "\033[%dA\033[J", lines);
 }
 
-void print_io_stats(struct bench *prefs, double elapsed)
+void print_divider()
 {
+       fprintf(stdout, "           ~~~~~~~~~~~~~~~~~~~~~~~~\n");
+}
+
+void print_io_stats(struct bench *prefs)
+{
+       struct timer *tm = prefs->total_tm;
        struct bw bw;
+       double elapsed;
        double iops;
 
-       /*
-        * We could malloc struct bw in __calculate_bw, but it's safer in cases when
-        * there is no memory left.
-        */
-       iops = __calculate_iops(prefs, elapsed);
+       if (!prefs->status->received) {
+               if (prefs->op == X_READ || prefs->op == X_WRITE)
+                       fprintf(stdout, "Bandwidth:    NaN\n");
+               fprintf(stdout, "IOPS:         NaN\n");
+               return;
+       }
+
+       elapsed = __timespec2double(tm->elapsed_time);
+       iops = __calculate_iops(prefs->rep->interval, elapsed);
        __calculate_bw(prefs, iops, &bw);
 
-       fprintf(stdout, "           ~~~~~~~~~~~~~~~~~~~~~~~~\n");
        if (prefs->op == X_READ || prefs->op == X_WRITE)
                fprintf(stdout, "Bandwidth:    %.3lf %s\n", bw.val, bw.unit);
        fprintf(stdout, "IOPS:         %.3lf\n", iops);
 }
 
-void print_stats(struct bench *prefs)
+void print_req_stats(struct bench *prefs)
 {
        fprintf(stdout, "\n"
                        "Requests total:     %10lu\n"
@@ -351,10 +414,11 @@ void print_stats(struct bench *prefs)
                        prefs->status->submitted,
                        prefs->status->received,
                        prefs->status->failed);
-       if ((prefs->op == X_READ) && (GET_FLAG(VERIFY, prefs->flags) != VERIFY_NO))
-               fprintf(stdout, "Requests corrupted: %10lu\n", prefs->status->corrupted);
+       if ((prefs->op == X_READ) &&
+                       (GET_FLAG(VERIFY, prefs->flags) != VERIFY_NO))
+               fprintf(stdout, "Requests corrupted: %10lu\n",
+                               prefs->status->corrupted);
        fprintf(stdout, "\n");
-       fflush(stdout);
 }
 
 void print_remaining(struct bench *prefs)
@@ -366,17 +430,14 @@ void print_remaining(struct bench *prefs)
                fprintf(stdout, "Requests remaining: %10lu\n", remaining);
        else
                fprintf(stdout, "All requests have been served.\n");
-       fflush(stdout);
 }
 
-void print_res(struct bench *prefs)
+void print_total_res(struct bench *prefs)
 {
-       struct timer *tm;
-       struct tm_result res, res_rec;
-       double sum, sum_rec;
+       struct timer *tm = prefs->total_tm;
+       struct tm_result res;
+       double sum;
 
-       /*  */
-       tm = prefs->total_tm;
        sum = __timespec2double(tm->sum);
        res = __separate_by_order(sum);
 
@@ -386,31 +447,48 @@ void print_res(struct bench *prefs)
        fprintf(stdout, "             |-s-||-ms-|-us-|-ns-|\n");
        fprintf(stdout, "Total time:   %3u. %03u  %03u  %03u\n",
                        res.s, res.ms, res.us, res.ns);
+}
+
+void print_rec_res(struct bench *prefs)
+{
+       struct timer *tm = prefs->rec_tm;
+       struct tm_result res;
+       double sum;
 
        if (!prefs->status->received) {
-               fflush(stdout);
+               fprintf(stdout, "Avg. latency: NaN\n");
                return;
        }
 
-       tm = prefs->rec_tm;
-       if (GET_FLAG(INSANITY, prefs->flags) < tm->insanity)
-               goto flush;
-
-       sum_rec = __timespec2double(tm->sum);
-       res_rec = __separate_by_order(sum_rec / prefs->status->received);
+       sum = __timespec2double(tm->sum);
+       res = __separate_by_order(sum / prefs->status->received);
 
        fprintf(stdout, "Avg. latency: %3u. %03u  %03u  %03u\n",
-                       res_rec.s, res_rec.ms, res_rec.us, res_rec.ns);
+                       res.s, res.ms, res.us, res.ns);
+}
+
+static void __print_progress(struct bench *prefs)
+{
+       int progress = GET_FLAG(PROGRESS, prefs->flags);
 
-flush:
-       print_io_stats(prefs, sum);
+       if (progress == PROGRESS_REQ || progress == PROGRESS_BOTH)
+                       print_req_stats(prefs);
+       if (progress == PROGRESS_IO ||  progress == PROGRESS_BOTH)
+                       print_io_stats(prefs);
        fflush(stdout);
 }
 
+void print_dummy_progress(struct bench *prefs)
+{
+       __print_progress(prefs);
+}
+
 void print_progress(struct bench *prefs)
 {
-       clear_lines(prefs);
-       print_stats(prefs);
+       timer_stop(prefs, prefs->total_tm, NULL);
+       clear_report_lines(prefs->rep->lines);
+       __print_progress(prefs);
+       timer_start(prefs, prefs->total_tm);
 }
 
 /**************************\
@@ -458,12 +536,6 @@ uint64_t calculate_offset(struct bench *prefs, uint64_t new)
                return 0;
 }
 
-uint64_t calculate_prog_quantum(struct bench *prefs)
-{
-       return round((double)prefs->status->max / 20.0);
-}
-
-
 /*
  * ***********************************************
  * `create_chunk` handles 3 identifiers:
index 02acb49..39e22ff 100644 (file)
  * c) If we are not in ping mode
  * d) If we have been asked to terminate
  */
-#define CAN_SEND_REQUEST(__p)                                          \
+#define CAN_SEND_REQUEST(__p)                                               \
        ((__p->status->submitted - __p->status->received < __p->iodepth) && \
-       (__p->status->submitted < __p->status->max) &&                  \
-       (GET_FLAG(PING, __p->flags) == PING_MODE_OFF) &&                \
+       (__p->status->submitted < __p->status->max) &&                      \
+       (GET_FLAG(PING, __p->flags) == PING_MODE_OFF) &&                    \
         !isTerminate())
 
-#define CAN_VERIFY(__p)                                                        \
+#define CAN_VERIFY(__p)                                                     \
        ((GET_FLAG(VERIFY, __p->flags) != VERIFY_NO) && __p->op == X_READ)
 
-#define CAN_PRINT_PROGRESS(__p, __q)                                   \
-       ((GET_FLAG(PROGRESS, __p->flags) == PROGRESS_YES) &&            \
-       (__p->status->received == __q))
+#define CAN_PRINT_PROGRESS(__p, __nr)                                       \
+       ((GET_FLAG(PROGRESS, __p->flags) != PROGRESS_NO) &&                 \
+       (GET_FLAG(PING, __p->flags) == PING_MODE_OFF) &&                    \
+       (__p->status->received == __nr))
 
 void custom_peer_usage()
 {
        fprintf(stderr, "Custom peer options: \n"
                "  --------------------------------------------\n"
-               "    -op       | None    | XSEG operation [read|write|info|delete]\n"
+               "    -op       | None    | XSEG operation:\n"
+               "              |         |     [read|write|info|delete]\n"
                "    --pattern | None    | I/O pattern [seq|rand]\n"
-               "    --verify  | no      | Verify written requests [no|meta|full]\n"
+               "    --verify  | no      | Verify written requests:\n"
+               "              |         |     [no|meta|full]\n"
                "    -rc       | None    | Request cap\n"
                "    -to       | None    | Total objects\n"
                "    -ts       | None    | Total I/O size\n"
@@ -86,11 +89,13 @@ void custom_peer_usage()
                "    --seed    | None    | Initialize LFSR and target names\n"
                "    --insanity| sane    | Adjust insanity level of benchmark:\n"
                "              |         |     [sane|eccentric|manic|paranoid]\n"
-               "    --progress| yes     | Show progress of requests [yes|no]\n"
-               "    --ping    | yes     | Ping target before starting benchmark\n"
+               "    --progress| both    | Show progress of benchmark:\n"
+               "              |         |     [req|io|both|no]\n"
+               "    --interval| 5%%     | Intervals at which progress is shown\n"
+               "    --ping    | yes     | Ping target before starting:\n"
                "              |         |     [yes|no]\n"
-               "    --prefix  | 'bench' | Add a common prefix to all object names\n"
-               "    --objname | 'bench' | Use only one object with this name\n"
+               "    --prefix  | bench   | Add a common prefix to all object names\n"
+               "    --objname | None    | Use only one object with this name\n"
                "\n"
                "Additional information:\n"
                "  --------------------------------------------\n"
@@ -123,8 +128,29 @@ void custom_peer_usage()
                "   a. -to option is strictly restricted to 1\n"
                "   b. -ts option defaults to (and can't be larger than)\n"
                "      the object size (-os argument)\n"
-               "   c. --prefix is must be unused. If used, it produces an "
+               "   c. --prefix is must be unused. If used, it produces an\n"
                "      error to alert the user\n"
+               "\n"
+               " * The progress report is printed by default at intervals of\n"
+               "   5%%.\n"
+               "   There are three progress types:\n"
+               "\n"
+               "   a. req: it prints the request status so far i.e. how many\n"
+               "      requests have been subitted, received, failed etc.\n"
+               "   b. io: it prints the bandwidth and IOPS status of the\n"
+               "      elapsed 5%% of the benchmark\n"
+               "   c. both: it combines the output of <req> and <io>.\n"
+               "\n"
+               " * Interval is commonly a percentage of max requests. This\n"
+               "   means that when a user gives:\n"
+               "           --interval 33%%\n"
+               "\n"
+               "   the progress report will be printed 3 times during the\n"
+               "   benchmark. Else, if the user wants to, he/she can give:\n"
+               "           --interval 1234\n"
+               "\n"
+               "  and the progress report will be printed every 1234\n"
+               "  requests.\n"
                "\n");
 }
 
@@ -141,6 +167,7 @@ int custom_peer_init(struct peerd *peer, int argc, char *argv[])
        char insanity[MAX_ARG_LEN + 1];
        char verify[MAX_ARG_LEN + 1];
        char progress[MAX_ARG_LEN + 1];
+       char interval[MAX_ARG_LEN + 1];
        char ping[MAX_ARG_LEN + 1];
        char prefix[XSEG_MAX_TARGETLEN + 1];
        char objname[XSEG_MAX_TARGETLEN + 1];
@@ -166,6 +193,7 @@ int custom_peer_init(struct peerd *peer, int argc, char *argv[])
        verify[0] = 0;
        request_cap[0] = 0;
        progress[0] = 0;
+       interval[0] = 0;
        ping[0] = 0;
        prefix[0] = 0;
        objname[0] = 0;
@@ -194,6 +222,14 @@ int custom_peer_init(struct peerd *peer, int argc, char *argv[])
        }
        memset(prefs->objvars, 0, sizeof(struct object_vars));
 
+       /* allocate struct object_name */
+       prefs->rep = malloc(sizeof(struct progress_report));
+       if (!prefs->rep) {
+               perror("malloc");
+               goto progress_report_fail;
+       }
+       memset(prefs->rep, 0, sizeof(struct progress_report));
+
        /* allocate a struct timespec for each peer request */
        for (j = 0; j < peer->nr_ops; j++) {
                ts = malloc(sizeof(struct timespec));
@@ -219,6 +255,7 @@ int custom_peer_init(struct peerd *peer, int argc, char *argv[])
        READ_ARG_STRING("--insanity", insanity, MAX_ARG_LEN);
        READ_ARG_STRING("--verify", verify, MAX_ARG_LEN);
        READ_ARG_STRING("--progress", progress, MAX_ARG_LEN);
+       READ_ARG_STRING("--interval", interval, MAX_ARG_LEN);
        READ_ARG_STRING("--ping", ping, MAX_ARG_LEN);
        READ_ARG_STRING("--prefix", prefix, XSEG_MAX_TARGETLEN);
        READ_ARG_STRING("--objname", objname, XSEG_MAX_TARGETLEN);
@@ -503,13 +540,37 @@ reseed:
 
        /* Benchmarking progress printing is on by default */
        if (!progress[0])
-               strcpy(progress, "yes");
+               strcpy(progress, "both");
        r = read_progress(progress);
        if (r < 0) {
                XSEGLOG2(&lc, E, "Invalid syntax: --progress %s\n", progress);
                goto arg_fail;
        }
        SET_FLAG(PROGRESS, prefs->flags, r);
+       prefs->rep->lines = calculate_report_lines(prefs);
+
+       /*
+        * Progress report interval definition makes no sense with disabled
+        * progress reports.
+        */
+       if ((GET_FLAG(PROGRESS, prefs->flags) == PROGRESS_NO) &&
+                       interval[0]) {
+               XSEGLOG2(&lc, E, "Cannot define progress interval without "
+                               "enabling progress report\n");
+               goto arg_fail;
+       }
+
+       if (GET_FLAG(PROGRESS, prefs->flags) != PROGRESS_NO) {
+               /* By default, we print every 5% */
+               if (!interval[0])
+                       strcpy(interval, "5%");
+               prefs->rep->interval = read_interval(prefs, interval);
+               if (prefs->rep->interval == 0) {
+                       XSEGLOG2(&lc, E, "Invalid syntax: --interval %s\n",
+                                       interval);
+                       goto arg_fail;
+               }
+       }
 
        /* Pinging the target peer is on by default */
        if (!ping[0])
@@ -548,6 +609,8 @@ priv_fail:
        for (; j >= 0; j--) {
                free(peer->peer_reqs[j].priv);
        }
+progress_report_fail:
+       free(prefs->rep);
 object_name_fail:
        free(prefs->objvars);
 status_fail:
@@ -757,34 +820,30 @@ int bench_peerd_loop(void *arg)
        xport portno_end = peer->portno_end;
        pid_t pid = syscall(SYS_gettid);
        uint64_t threshold=1000/(1 + portno_end - portno_start);
-       uint64_t cached_prog_quantum = 0;
-       uint64_t prog_quantum = 0;
-       int r;
+       uint64_t next_report = prefs->rep->interval;
        uint64_t loops;
-
-       if (GET_FLAG(PROGRESS, prefs->flags) == PROGRESS_YES) {
-               prog_quantum = calculate_prog_quantum(prefs);
-               cached_prog_quantum = prog_quantum;
-               print_stats(prefs);
-       }
+       int r;
 
        XSEGLOG2(&lc, I, "%s has tid %u.\n",id, pid);
        xseg_init_local_signal(xseg, peer->portno_start);
 
+       if (GET_FLAG(PROGRESS, prefs->flags) != PROGRESS_NO)
+               print_dummy_progress(prefs);
+
        /* If no ping is going to be sent, we can begin the benchmark now. */
-       if (GET_FLAG(PING, prefs->flags) == PING_MODE_OFF)
-               timer_start(prefs, prefs->total_tm);
-       else
+       if (GET_FLAG(PING, prefs->flags) == PING_MODE_ON)
                send_ping_request(peer, prefs);
+       else
+               timer_start(prefs, prefs->total_tm);
 
 send_request:
        while (!(isTerminate() && all_peer_reqs_free(peer))) {
                while (CAN_SEND_REQUEST(prefs)) {
                        xseg_cancel_wait(xseg, peer->portno_start);
                        XSEGLOG2(&lc, D, "...because %lu < %lu && %lu < %lu\n",
-                                       prefs->status->submitted - prefs->status->received,
-                                       prefs->iodepth, prefs->status->received,
-                                       prefs->status->max);
+                               prefs->status->submitted - prefs->status->received,
+                               prefs->iodepth, prefs->status->received,
+                               prefs->status->max);
                        XSEGLOG2(&lc, D, "Start sending new request\n");
                        r = send_request(peer, prefs);
                        if (r < 0)
@@ -795,25 +854,21 @@ send_request:
                        if (loops == 1)
                                xseg_prepare_wait(xseg, peer->portno_start);
 
-                       if (UNLIKELY(CAN_PRINT_PROGRESS(prefs, prog_quantum))) {
-                               prog_quantum += cached_prog_quantum;
+                       if (CAN_PRINT_PROGRESS(prefs, next_report)) {
                                print_progress(prefs);
+                               next_report += prefs->rep->interval;
                        }
 
                        if (check_ports(peer)) {
-                               //If an old request has just been acked, the most sensible
-                               //thing to do is to immediately send a new one
+                               //If an old request has just been acked, the
+                               //most sensible thing to do is to immediately
+                               //send a new one
                                if (prefs->status->received < prefs->status->max)
                                        goto send_request;
                                else
                                        return 0;
                        }
                }
-               //struct xseg_port *port = xseg_get_port(xseg, portno_start);
-               //struct xq *q;
-               //q = XPTR_TAKE(port->request_queue, xseg->segment);
-               //XSEGLOG2(&lc, I, "%s goes to sleep with %u requests pending\n",
-               //              id, xq_count(q));
                XSEGLOG2(&lc, I, "%s goes to sleep\n", id);
                xseg_wait_signal(xseg, 10000000UL);
                xseg_cancel_wait(xseg, peer->portno_start);
@@ -830,15 +885,32 @@ void custom_peer_finalize(struct peerd *peer)
        struct bench *prefs = peer->priv;
        //TODO: Measure mean time, standard variation
 
-       if (!prefs->total_tm->completed)
-               timer_stop(prefs, prefs->total_tm, NULL);
+       timer_stop(prefs, prefs->total_tm, NULL);
 
-       if (GET_FLAG(PROGRESS, prefs->flags) == PROGRESS_YES)
-               clear_lines(prefs);
+       if (GET_FLAG(PROGRESS, prefs->flags) != PROGRESS_NO)
+               clear_report_lines(prefs->rep->lines);
 
-       print_stats(prefs);
+       print_req_stats(prefs);
        print_remaining(prefs);
-       print_res(prefs);
+       print_total_res(prefs);
+
+       if (GET_FLAG(INSANITY, prefs->flags) >= prefs->rec_tm->insanity)
+               print_rec_res(prefs);
+
+       print_divider();
+       /*
+        * This is kinda hacky but is reasonable.
+        * During the benchmark, we need to calculate the bandwidth within an
+        * interval.
+        * After the benchmark, we need to calculate the total bandwidth. To do
+        * so, we treat the benchmark as one single interval, and that's what
+        * the two lines below do. This way, the same code can aplly to both
+        * cases
+        */
+       prefs->total_tm->elapsed_time = prefs->total_tm->sum;
+       prefs->rep->interval = prefs->status->received;
+       print_io_stats(prefs);
+       fflush(stdout);
        return;
 }
 
index 773099d..6847428 100644 (file)
 
 /* Progress bar option occupies 6th flag bit */
 #define PROGRESS_FLAG_POS 5
-#define PROGRESS_BITMASK 1
+#define PROGRESS_BITMASK 3     /* i.e. "11" in binary form */
 #define PROGRESS_NO 0
-#define PROGRESS_YES 1
+#define PROGRESS_REQ 1
+#define PROGRESS_IO 2
+#define PROGRESS_BOTH 3
 
 /* Ping option occupies 7th flag bit */
-#define PING_FLAG_POS 6
+#define PING_FLAG_POS 7
 #define PING_BITMASK 1
 #define PING_MODE_OFF 0
 #define PING_MODE_ON 1
 
 /*
  * Current bench flags representation:
- * 64  8  7  6  5  4  3  2  1 : bits
- * ... 0  0  0  0  0  0  0  0
- *       |_||_||____||____||_|
- *        ^  ^   ^     ^   ^
- *       |  |    |     |   |
- *     ping | insanity | pattern
- *       progress   verify
+ * 64  9  8  7  6  5  4  3  2  1 : bits
+ * ... 0  0  0  0  0  0  0  0  0
+ *       |_||____||____||____||_|
+ *        ^    ^    ^    ^    ^
+ *       |    |    |     |    |
+ *     ping   | insanity | pattern
+ *          progress   verify
  */
 
 /*
@@ -137,10 +139,12 @@ struct bench {
        xport src_port;
        uint32_t op;    //xseg operation
        uint64_t flags;
+       unsigned int interval;
        struct peerd *peer;
        struct req_status *status;
        struct bench_lfsr *lfsr;
        struct object_vars *objvars;
+       struct progress_report *rep;
        struct timer *total_tm; //Total time for benchmark
        struct timer *get_tm;   //Time for xseg_get_request
        struct timer *sub_tm;   //Time for xseg_submit_request
@@ -166,6 +170,12 @@ struct req_status {
        uint64_t failed;
 };
 
+struct progress_report {
+       uint64_t prev_recv;
+       uint64_t interval;
+       int lines;
+};
+
 /*
  * Custom timespec. Made to calculate variance, where we need the square of a
  * timespec struct. This struct should be more than enough to hold the square
@@ -225,18 +235,24 @@ int read_pattern(char *pattern);
 int read_insanity(char *insanity);
 int read_verify(char *insanity);
 int read_progress(char *progress);
+uint64_t read_interval(struct bench *prefs, char *str_interval);
 int read_ping(char *progress);
-void clear_lines(struct bench *prefs);
-void print_res(struct bench *prefs);
-void print_stats(struct bench *prefs);
+void clear_report_lines(int lines);
+void print_total_res(struct bench *prefs);
+void print_rec_res(struct bench *prefs);
+void print_divider();
+void print_req_stats(struct bench *prefs);
+void print_io_stats(struct bench *prefs);
 void print_progress(struct bench *prefs);
+void print_dummy_progress(struct bench *prefs);
 void print_remaining(struct bench *prefs);
 void create_target(struct bench *prefs, struct xseg_request *req);
 void create_chunk(struct bench *prefs, struct xseg_request *req, uint64_t new);
 int read_chunk(struct bench *prefs, struct xseg_request *req);
 uint64_t determine_next(struct bench *prefs);
 uint64_t calculate_offset(struct bench *prefs, uint64_t new);
-uint64_t calculate_prog_quantum(struct bench *prefs);
+uint64_t calculate_interval(struct bench *prefs, uint64_t percentage);
+int calculate_report_lines(struct bench *prefs);
 int validate_seed(struct bench *prefs, unsigned long seed);
 
 void inspect_obv(struct object_vars *obv);