Add proper per-file copyright notices/licenses and top-level license.
[bluesky.git] / nfs3 / synreadbench.c
index f4d5ad2..b27d9f1 100644 (file)
@@ -3,7 +3,29 @@
  * Copyright (C) 2009  The Regents of the University of California
  * Written by Michael Vrable <mvrable@cs.ucsd.edu>
  *
- * TODO: Licensing
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
  */
 
 /* Synthetic client for benchmarking: a tool for directly generating NFS
@@ -35,6 +57,9 @@
 /* Maximum size of a single RPC message that we will accept (8 MB). */
 #define MAX_RPC_MSGSIZE (8 << 20)
 
+FILE *logfile = NULL;
+
+int warmup_mode = 0;
 int threads;
 int completed = 0;
 int read_size = 32768;
@@ -44,6 +69,11 @@ struct bench_file {
     uint64_t size;
 };
 
+struct data_point {
+    uint32_t timestamp;     // Unix timestamp of completion
+    uint32_t latency;       // Latency, in microseconds
+} __attribute__((packed));
+
 GArray *bench_files;
 
 struct rpc_reply {
@@ -187,18 +217,30 @@ static void process_reply(NFSConnection *nfs, GString *msg)
         return;
     }
 
+    struct data_point d;
     info->end = now_hires();
-    printf("XID %d: Time = %"PRIi64"\n", xid, info->end - info->start);
+    d.timestamp = info->end / 1000000000;
+    d.latency = (info->end - info->start + 500) / 1000; /* Round off */
+    //printf("XID %d: Time = %"PRIi64"\n", xid, info->end - info->start);
     if (info->callback != NULL)
         info->callback(nfs, info->user_data,
                        msg->str + sizeof(*reply), msg->len - sizeof(*reply));
 
     g_hash_table_remove(nfs->xid_table, key);
     g_free(info);
+    if (logfile != NULL) {
+        fwrite(&d, sizeof(d), 1, logfile);
+        fflush(logfile);
+    }
 
     completed++;
-    if (completed == 128 * threads) {
-        g_main_loop_quit(main_loop);
+    if (warmup_mode) {
+        printf("Done warming up %d\n", completed);
+        int scale = 1;
+        if (read_size > (1 << 20))
+            scale = read_size / (1 << 20);
+        if (completed == bench_files->len * scale)
+            g_main_loop_quit(main_loop);
     }
 }
 
@@ -284,7 +326,26 @@ static void send_read_request(NFSConnection *nfs, uint64_t inum,
                                uint64_t offset, uint64_t len);
 static void submit_random_read(NFSConnection *nfs)
 {
+    static int warmup_counter = 0;
     struct bench_file *bf;
+
+    if (warmup_mode) {
+        int scale = 1;
+        if (read_size > (1 << 20)) {
+            scale = read_size / (1 << 20);
+        }
+        int filecount = bench_files->len;
+        printf("Warming up file %d\n", warmup_counter);
+        if (warmup_counter >= filecount * scale)
+            return;
+        bf = &g_array_index(bench_files, struct bench_file,
+                            warmup_counter % filecount);
+        send_read_request(nfs, bf->inum, (warmup_counter / filecount) << 20,
+                          read_size > (1 << 20) ? (1 << 20) : read_size);
+        warmup_counter++;
+        return;
+    }
+
     bf = &g_array_index(bench_files, struct bench_file,
                         g_random_int_range(0, bench_files->len));
     int blocks = bf->size / read_size;
@@ -298,8 +359,6 @@ static void submit_random_read(NFSConnection *nfs)
 static void finish_read_request(NFSConnection *nfs, gpointer user_data,
                                 const char *reply, size_t len)
 {
-    printf("Done reading inode %d\n", GPOINTER_TO_INT(user_data));
-
     submit_random_read(nfs);
 }
 
@@ -384,7 +443,7 @@ NFSConnection *nfs_connect(const char *hostname)
     }
 
     if (connect(fd, ai->ai_addr, ai->ai_addrlen) < 0) {
-        fprintf(stderr, "Unable to connect to : %m\n");
+        fprintf(stderr, "Unable to connect to %s: %m\n", hostname);
     }
 
     freeaddrinfo(ai);
@@ -407,7 +466,6 @@ int main(int argc, char *argv[])
 {
     g_thread_init(NULL);
     g_set_prgname("synclient");
-    g_print("Launching synthetic NFS RPC client...\n");
 
     bench_files = g_array_new(FALSE, TRUE, sizeof(struct bench_file));
 
@@ -427,15 +485,23 @@ int main(int argc, char *argv[])
         bf.size = i2;
         g_array_append_val(bench_files, bf);
     }
+    fclose(inodes);
 
     threads = 8;
     if (argc > 2)
         threads = atoi(argv[2]);
     if (argc > 3)
         read_size = atoi(argv[3]);
+    if (argc > 4) {
+        if (strcmp(argv[4], "WARMUP") == 0) {
+            warmup_mode = 1;
+        } else {
+            logfile = fopen(argv[4], "wb");
+        }
+    }
 
     main_loop = g_main_loop_new(NULL, FALSE);
-    nfs_connect("niniel.sysnet.ucsd.edu");
+    nfs_connect("vrable2.sysnet.ucsd.edu");
 
     g_main_loop_run(main_loop);