Add progress report for bench
authorAlex Pyrgiotis <apyrgio@grnet.gr>
Fri, 15 Mar 2013 15:43:03 +0000 (17:43 +0200)
committerAlex Pyrgiotis <apyrgio@grnet.gr>
Thu, 18 Apr 2013 15:39:39 +0000 (18:39 +0300)
Progress report is turned on by default. It reports every 5% the current
request status.
Also, we now make sure to terminate only if all peer requests are free.

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

index ebdd421..d884514 100644 (file)
@@ -226,6 +226,15 @@ int read_verify(char *verify)
        return -1;
 }
 
+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;
+       return -1;
+}
+
 int read_pattern(char *pattern)
 {
        if (strncmp(pattern, "seq", MAX_ARG_LEN + 1) == 0)
@@ -241,16 +250,23 @@ int read_pattern(char *pattern)
 
 void print_stats(struct bench *prefs)
 {
-       uint64_t remaining;
-
-       printf("\n");
-       printf("Requests total:     %10lu\n", prefs->status->max);
-       printf("Requests submitted: %10lu\n", prefs->status->submitted);
-       printf("Requests received:  %10lu\n", prefs->status->received);
-       printf("Requests failed:    %10lu\n", prefs->status->failed);
+       printf("\n"
+                       "Requests total:     %10lu\n"
+                       "Requests submitted: %10lu\n"
+                       "Requests received:  %10lu\n"
+                       "Requests failed:    %10lu\n",
+                       prefs->status->max,
+                       prefs->status->submitted,
+                       prefs->status->received,
+                       prefs->status->failed);
        if ((prefs->op == X_READ) && (GET_FLAG(VERIFY, prefs->flags) != VERIFY_NO))
                printf("Requests corrupted: %10lu\n", prefs->status->corrupted);
        printf("\n");
+}
+
+void print_remaining(struct bench *prefs)
+{
+       uint64_t remaining;
 
        remaining = prefs->status->max - prefs->status->received;
        if (remaining)
@@ -285,6 +301,17 @@ void print_res(struct bench *prefs, struct timer *tm, char *type)
        //TODO: Add std
 }
 
+void print_progress(struct bench *prefs)
+{
+       int lines = 6;
+
+       if ((prefs->op == X_READ) && (GET_FLAG(VERIFY, prefs->flags) != VERIFY_NO))
+               lines++;
+
+       printf("\033[%dA\033[J", lines);
+       print_stats(prefs);
+}
+
 /**************************\
  * Benchmarking functions *
 \**************************/
@@ -331,6 +358,12 @@ 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 d111191..f78059e 100644 (file)
@@ -54,12 +54,17 @@ char global_id[IDLEN];
  * a) If in-flight requests are less than given iodepth
  * b) If we have submitted all of the requests
  */
-#define CAN_SEND_REQUEST(prefs)                                                                                                  \
-       ((prefs->status->submitted - prefs->status->received < prefs->iodepth) && \
-       (prefs->status->submitted < prefs->status->max))
+#define CAN_SEND_REQUEST(__p)                                                                                  \
+       ((__p->status->submitted - __p->status->received < __p->iodepth) && \
+       (__p->status->submitted < __p->status->max) &&                                          \
+       !isTerminate())
 
-#define CAN_VERIFY(prefs)                                                                                                        \
-       ((GET_FLAG(VERIFY, prefs->flags) != VERIFY_NO) && prefs->op == X_READ)
+#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))
 
 void custom_peer_usage()
 {
@@ -78,6 +83,7 @@ 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\n"
                        "\n"
                        "Additional information:\n"
                        "  --------------------------------------------\n"
@@ -97,6 +103,7 @@ int custom_peer_init(struct peerd *peer, int argc, char *argv[])
        char pattern[MAX_ARG_LEN + 1];
        char insanity[MAX_ARG_LEN + 1];
        char verify[MAX_ARG_LEN + 1];
+       char progress[MAX_ARG_LEN + 1];
        struct xseg *xseg = peer->xseg;
        unsigned int xseg_page_size = 1 << xseg->config.page_shift;
        long iodepth = -1;
@@ -116,6 +123,7 @@ int custom_peer_init(struct peerd *peer, int argc, char *argv[])
        insanity[0] = 0;
        verify[0] = 0;
        request_cap[0] = 0;
+       progress[0] = 0;
 
 #ifdef MT
        for (i = 0; i < nr_threads; i++) {
@@ -155,6 +163,7 @@ int custom_peer_init(struct peerd *peer, int argc, char *argv[])
        READ_ARG_ULONG("--seed", seed);
        READ_ARG_STRING("--insanity", insanity, MAX_ARG_LEN);
        READ_ARG_STRING("--verify", verify, MAX_ARG_LEN);
+       READ_ARG_STRING("--progress", progress, MAX_ARG_LEN);
        END_READ_ARGS();
 
        /*****************************\
@@ -348,9 +357,9 @@ reseed:
                }
        }
 
-       /****************************\
-        * Finalize initializations *
-       \****************************/
+       /*********************************\
+        * Miscellaneous initializations *
+       \*********************************/
 
        /* The request cap must be enforced only after the LFSR is initialized */
        if (request_cap[0]) {
@@ -365,6 +374,16 @@ reseed:
                prefs->status->max = rc;
        }
 
+       /* Benchmarking progress printing is on by default */
+       if (!progress[0])
+               strcpy(progress, "yes");
+       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->peer = peer;
        peer->peerd_loop = bench_peerd_loop;
        peer->priv = (void *) prefs;
@@ -516,27 +535,25 @@ int bench_peerd_loop(void *arg)
        struct bench *prefs = peer->priv;
        xport portno_start = peer->portno_start;
        xport portno_end = peer->portno_end;
-       uint64_t threshold=1000/(1 + portno_end - portno_start);
        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 loops;
 
+       if (GET_FLAG(PROGRESS, prefs->flags) == PROGRESS_YES) {
+               prog_quantum = calculate_prog_quantum(prefs);
+               cached_prog_quantum = prog_quantum;
+               print_stats(prefs);
+       }
+
        XSEGLOG2(&lc, I, "%s has tid %u.\n",id, pid);
        xseg_init_local_signal(xseg, peer->portno_start);
 
        timer_start(prefs, prefs->total_tm);
 send_request:
-       while (!isTerminate()) {
-#ifdef MT
-               if (t->func) {
-                       XSEGLOG2(&lc, D, "%s executes function\n", id);
-                       xseg_cancel_wait(xseg, peer->portno_start);
-                       t->func(t->arg);
-                       t->func = NULL;
-                       t->arg = NULL;
-                       continue;
-               }
-#endif
+       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",
@@ -553,6 +570,11 @@ 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;
+                               print_progress(prefs);
+                       }
+
                        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
@@ -568,12 +590,6 @@ send_request:
                //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);
-#ifdef ST_THREADS
-               if (ta){
-                       st_sleep(0);
-                       continue;
-               }
-#endif
                xseg_wait_signal(xseg, 10000000UL);
                xseg_cancel_wait(xseg, peer->portno_start);
                XSEGLOG2(&lc, I, "%s woke up\n", id);
@@ -592,7 +608,12 @@ void custom_peer_finalize(struct peerd *peer)
        if (!prefs->total_tm->completed)
                timer_stop(prefs, prefs->total_tm, NULL);
 
-       print_stats(prefs);
+       if (GET_FLAG(PROGRESS, prefs->flags) == PROGRESS_YES)
+               print_progress(prefs);
+       else
+               print_stats(prefs);
+
+       print_remaining(prefs);
        print_res(prefs, prefs->total_tm, "Total Requests");
        return;
 }
index e583442..6c9b367 100644 (file)
 
 #include <bench-lfsr.h>
 
+
+#ifdef __GNUC__
+#define LIKELY(x)       __builtin_expect(!!(x),1)
+#define UNLIKELY(x)     __builtin_expect(!!(x),0)
+#else
+#define LIKELY(x)       (x)
+#define UNLIKELY(x)     (x)
+#endif
+
 /*
  * If CLOCK_MONOTONIC_RAW is not defined in our system, use CLOCK_MONOTONIC
  * instead. CLOCK_MONOTONIC_RAW is preferred since we are guaranteed that the
 #define INSANITY_MANIC 2
 #define INSANITY_PARANOID 3
 
+/* Progress bar option occupies 6th flag bit */
+#define PROGRESS_FLAG_POS 5
+#define PROGRESS_BITMASK 1     /* i.e. "11" in binary form */
+#define PROGRESS_NO 0
+#define PROGRESS_YES 1
 
 /*
  * Current bench flags representation:
  * 64 7  6  5  4  3  2  1 : bits
  * ...0  0  0  0  0  0  0
- *         |____||____||_|
- *                       ^         ^   ^
- *                       |             |   |
- *                insanity     | pattern
- *                              verify
+ *      |_||____||____||_|
+ *              ^        ^         ^   ^
+ *              |        |             |   |
+ *              | insanity     | pattern
+ *       progress       verify
+ */
+
+/*
+ * Find position of flag, make it zero, get requested flag value, store it to
+ * this position
  */
-/* Add flag bit according to its position */
 #define SET_FLAG(__ftype, __flag, __val)       \
-       __flag |= __val << __ftype##_FLAG_POS;
+       __flag = (__flag & ~(__ftype##_BITMASK << __ftype##_FLAG_POS)) | \
+       (__val << __ftype##_FLAG_POS);
 
 /* Apply bitmask to flags, shift result to the right to get correct value */
 #define GET_FLAG(__ftype, __flag)                      \
        (__flag & (__ftype##_BITMASK << __ftype##_FLAG_POS)) >> __ftype##_FLAG_POS
+
 /*
  * The benchark ID (IDLEN) is global for the test, calculated once and is a
  * string of the following form: {"bench-" + 9-digit number + "\0"}.
@@ -172,7 +192,6 @@ struct signature {
        uint64_t offset;
 };
 
-
 int bench_peerd_loop(void *arg);
 
 void timer_start(struct bench *prefs, struct timer *sample_req);
@@ -184,13 +203,17 @@ int read_op(char *op);
 int read_pattern(char *pattern);
 int read_insanity(char *insanity);
 int read_verify(char *insanity);
+int read_progress(char *progress);
 void print_res(struct bench *prefs, struct timer *tm, char *type);
 void print_stats(struct bench *prefs);
+void print_progress(struct bench *prefs);
+void print_remaining(struct bench *prefs);
 void create_target(struct bench *prefs, struct xseg_request *req,
                uint64_t new);
 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);
 void create_id(unsigned long seed);