r3976: changed NBENCH to use the same recording method as the latest dbench,
authorAndrew Tridgell <tridge@samba.org>
Thu, 25 Nov 2004 23:05:43 +0000 (23:05 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:06:10 +0000 (13:06 -0500)
where the warmup phase continues until all clients have done some file
IO. This gives more repeatable results when under high load
(This used to be commit aca0658f6dfe8b7c90afcac87e8cc68965a4288d)

source4/lib/time.c
source4/torture/nbench/nbench.c
source4/torture/nbench/nbio.c

index b13ad24b34c488528db8c36543c136ec16b5ab7f..8d477fac02e221d29afb44858d9b3f1b81014b87 100644 (file)
@@ -476,14 +476,22 @@ BOOL timeval_expired(struct timeval *tv)
        return (tv2.tv_usec >= tv->tv_usec);
 }
 
+/*
+  return the number of seconds elapsed between two times
+*/
+double timeval_elapsed2(struct timeval *tv1, struct timeval *tv2)
+{
+       return (tv2->tv_sec - tv1->tv_sec) + 
+              (tv2->tv_usec - tv1->tv_usec)*1.0e-6;
+}
+
 /*
   return the number of seconds elapsed since a given time
 */
 double timeval_elapsed(struct timeval *tv)
 {
        struct timeval tv2 = timeval_current();
-       return (tv2.tv_sec - tv->tv_sec) + 
-              (tv2.tv_usec - tv->tv_usec)*1.0e-6;
+       return timeval_elapsed2(tv, &tv2);
 }
 
 /*
@@ -497,6 +505,17 @@ struct timeval timeval_min(struct timeval *tv1, struct timeval *tv2)
        return *tv2;
 }
 
+/*
+  return the greater of two timevals
+*/
+struct timeval timeval_max(struct timeval *tv1, struct timeval *tv2)
+{
+       if (tv1->tv_sec > tv2->tv_sec) return *tv1;
+       if (tv1->tv_sec < tv2->tv_sec) return *tv2;
+       if (tv1->tv_usec > tv2->tv_usec) return *tv1;
+       return *tv2;
+}
+
 /*
   return the difference between two timevals as a timeval
   if tv2 comes after tv1, then return a zero timeval
index 1c90658f49cf4f27e89438da349f3a4edfed2a28..afd71537a91cf3e1e56636262c2006fe84459462 100644 (file)
@@ -37,11 +37,8 @@ static BOOL run_netbench(struct smbcli_state *cli, int client)
        fstring params[20];
        const char *p;
        BOOL correct = True;
-       struct timeval tv;
 
-       tv = timeval_current();
-
-       nb_setup(cli, client, warmup);
+       nb_setup(cli, client);
 
        asprintf(&cname, "client%d", client+1);
 
@@ -56,17 +53,6 @@ again:
        while (fgets(line, sizeof(line)-1, f)) {
                NTSTATUS status;
 
-               if (warmup && 
-                   timeval_elapsed(&tv) >= warmup) {
-                       warmup = 0;
-                       nb_warmup_done();
-                       tv = timeval_current();
-               }
-
-               if (timeval_elapsed(&tv) >= timelimit) {
-                       goto done;
-               }
-
                nbench_line_count++;
 
                line[strlen(line)-1] = 0;
@@ -147,6 +133,8 @@ again:
                } else {
                        printf("[%d] Unknown operation %s\n", nbench_line_count, params[0]);
                }
+               
+               if (nb_tick()) goto done;
        }
 
        rewind(f);
@@ -154,7 +142,6 @@ again:
 
 done:
        fclose(f);
-       nb_cleanup(cname);
 
        if (!torture_close_connection(cli)) {
                correct = False;
@@ -188,10 +175,11 @@ BOOL torture_nbench(void)
                return False;
        }
 
-       nb_setup(cli, -1, warmup);
-       nb_deltree("\\clients");
+       if (!torture_setup_dir(cli, "\\clients")) {
+               return False;
+       }
 
-       nbio_shmem(torture_nprocs);
+       nbio_shmem(torture_nprocs, timelimit, warmup);
 
        printf("Running for %d seconds with load '%s' and warmup %d secs\n", 
               timelimit, loadfile, warmup);
@@ -201,7 +189,8 @@ BOOL torture_nbench(void)
        torture_create_procs(run_netbench, &correct);
        alarm(0);
 
-       printf("\nThroughput %g MB/sec\n", 
-              1.0e-6 * nbio_total() / timelimit);
+       smbcli_deltree(cli->tree, "\\clients");
+
+       printf("\nThroughput %g MB/sec\n", nbio_result());
        return correct;
 }
index 98967f252330e2fd1a31c47b510b58160fc3909b..e3c40f9ba1e560f09c628bfec2f35886340eb541 100644 (file)
 #define MAX_FILES 100
 
 extern int nbench_line_count;
-static int nbio_id;
+static int nbio_id = -1;
 static int nprocs;
 static BOOL bypass_io;
-static int warmup;
-static struct timeval tv;
+static struct timeval tv_start, tv_end;
+static int warmup, timelimit;
+static int in_cleanup;
 
 struct ftable {
        struct ftable *next, *prev;
@@ -42,67 +43,90 @@ struct ftable {
 static struct ftable *ftable;
 
 static struct {
-       double bytes_in, bytes_out;
+       double bytes, warmup_bytes;
        int line;
        int done;
 } *children;
 
-double nbio_total(void)
+double nbio_result(void)
 {
        int i;
        double total = 0;
        for (i=0;i<nprocs;i++) {
-               total += children[i].bytes_out + children[i].bytes_in;
+               total += children[i].bytes - children[i].warmup_bytes;
        }
-       return total;
+       return 1.0e-6 * total / timeval_elapsed2(&tv_start, &tv_end);
 }
 
-void nb_warmup_done(void)
+BOOL nb_tick(void)
 {
-       children[nbio_id].bytes_out = 0;
-       children[nbio_id].bytes_in = 0;
+       return children[nbio_id].done;
 }
 
 
 void nb_alarm(int sig)
 {
        int i;
-       int lines=0, num_clients=0;
+       int lines=0;
        double t;
+       int in_warmup = 0;
 
        if (nbio_id != -1) return;
 
        for (i=0;i<nprocs;i++) {
+               if (children[i].bytes == 0) {
+                       in_warmup = 1;
+               }
                lines += children[i].line;
-               if (!children[i].done) num_clients++;
        }
 
-       t = timeval_elapsed(&tv);
+       t = timeval_elapsed(&tv_start);
 
-       if (warmup) {
+       if (!in_warmup && warmup>0 && t > warmup) {
+               tv_start = timeval_current();
+               warmup = 0;
+               for (i=0;i<nprocs;i++) {
+                       children[i].warmup_bytes = children[i].bytes;
+               }
+               goto next;
+       }
+       if (t < warmup) {
+               in_warmup = 1;
+       } else if (!in_warmup && !in_cleanup && t > timelimit) {
+               for (i=0;i<nprocs;i++) {
+                       children[i].done = 1;
+               }
+               tv_end = timeval_current();
+               in_cleanup = 1;
+       }
+       if (t < 1) {
+               goto next;
+       }
+       if (!in_cleanup) {
+               tv_end = timeval_current();
+       }
+
+       if (in_warmup) {
                printf("%4d  %8d  %.2f MB/sec  warmup %.0f sec   \n", 
-                      num_clients, lines/nprocs, 
-                      1.0e-6 * nbio_total() / t, 
-                      t);
+                      nprocs, lines/nprocs, 
+                      nbio_result(), t);
+       } else if (in_cleanup) {
+               printf("%4d  %8d  %.2f MB/sec  cleanup %.0f sec   \n", 
+                      nprocs, lines/nprocs, 
+                      nbio_result(), t);
        } else {
                printf("%4d  %8d  %.2f MB/sec  execute %.0f sec   \n", 
-                      num_clients, lines/nprocs, 
-                      1.0e-6 * nbio_total() / t, 
-                      t);
-       }
-
-       if (warmup && t >= warmup) {
-               tv = timeval_current();
-               warmup = 0;
+                      nprocs, lines/nprocs, 
+                      nbio_result(), t);
        }
 
        fflush(stdout);
-
+next:
        signal(SIGALRM, nb_alarm);
        alarm(1);       
 }
 
-void nbio_shmem(int n)
+void nbio_shmem(int n, int t_timelimit, int t_warmup)
 {
        nprocs = n;
        children = shm_setup(sizeof(*children) * nprocs);
@@ -110,6 +134,11 @@ void nbio_shmem(int n)
                printf("Failed to setup shared memory!\n");
                exit(1);
        }
+       memset(children, 0, sizeof(*children) * nprocs);
+       timelimit = t_timelimit;
+       warmup = t_warmup;
+       in_cleanup = 0;
+       tv_start = timeval_current();
 }
 
 static struct ftable *find_ftable(int handle)
@@ -152,15 +181,10 @@ static BOOL oplock_handler(struct smbcli_transport *transport, uint16_t tid, uin
        return smbcli_oplock_ack(tree, fnum, level);
 }
 
-void nb_setup(struct smbcli_state *cli, int id, int warmupt)
+void nb_setup(struct smbcli_state *cli, int id)
 {
-       warmup = warmupt;
        nbio_id = id;
        c = cli;
-       tv = timeval_current();
-       if (children) {
-               children[nbio_id].done = 0;
-       }
        if (bypass_io)
                printf("skipping I/O\n");
 
@@ -297,7 +321,7 @@ void nb_writex(int handle, int offset, int size, int ret_size, NTSTATUS status)
                       io.writex.out.nwritten, ret_size);
        }       
 
-       children[nbio_id].bytes_out += ret_size;
+       children[nbio_id].bytes += ret_size;
 }
 
 void nb_write(int handle, int offset, int size, int ret_size, NTSTATUS status)
@@ -334,7 +358,7 @@ void nb_write(int handle, int offset, int size, int ret_size, NTSTATUS status)
                       io.write.out.nwritten, ret_size);
        }       
 
-       children[nbio_id].bytes_out += ret_size;
+       children[nbio_id].bytes += ret_size;
 }
 
 
@@ -424,7 +448,7 @@ void nb_readx(int handle, int offset, int size, int ret_size, NTSTATUS status)
                exit(1);
        }       
 
-       children[nbio_id].bytes_in += ret_size;
+       children[nbio_id].bytes += ret_size;
 }
 
 void nb_close(int handle, NTSTATUS status)
@@ -649,12 +673,3 @@ void nb_deltree(const char *dname)
        smbcli_rmdir(c->tree, dname);
 }
 
-void nb_cleanup(const char *cname)
-{
-       char *dname = NULL;
-       asprintf(&dname, "\\clients\\%s", cname);
-       nb_deltree(dname);
-       free(dname);
-       smbcli_rmdir(c->tree, "clients");
-       children[nbio_id].done = 1;
-}