simoop: get rid of rw_threads, make defaults saner

simoop was originally meant to replicate what java was doing with
hadoop, so it sprayed new threads all over the place for little to no
reason.  This isn't ideal for careful timing, so instead do reads and
writes directly from the worker threads.

Before, read/write latencies covered the whole time it took to
pthread_create(), do 128 IOs, pthread_join().  Now the read/write
latencies cover the time required for a single read or write on a single
file.

The timings do include the fadvise(DONT_NEED) or any sync_file_range()
from write_through mode.

This commit also makes the defaults for think time and memory hogging 0.
The idea is to start benchmarking just the IO.

Signed-off-by: Chris Mason <clm@fb.com>
diff --git a/simoop.c b/simoop.c
index f73bb64..193330f 100644
--- a/simoop.c
+++ b/simoop.c
@@ -66,7 +66,7 @@
 /* -r  seconds */
 static unsigned long runtime = 30;
 /* -c  usec */
-static unsigned long long cputime = 3000000;
+static unsigned long long cputime = 0;
 /* -f size of the files we create */
 static unsigned long long file_size = 64 * 1024 * 1024;
 /* -n number of files we create */
@@ -75,8 +75,6 @@
 static unsigned long read_size = 2 * 1024 * 1024;
 /* -W write size */
 static unsigned long write_size = 2 * 1024 * 1024;
-/* -T number of files to read */
-static unsigned long rw_threads = 8;
 /* -D number of threads running du */
 static int du_threads = 0;
 /* memory to allocate and use during each task */
@@ -84,30 +82,34 @@
 /* should we fsync sometimes? */
 static int funksync = 0;
 static int writethrough = 0;
+
 /* are we just appending bytes onto the ends of the working set files */
 static int append_mode = 0;
 static int truncate_original = 0;
+
 /* dont do any crc checks -I */
 static int ignore_crcs = 0;
+
 /* randomize the write size */
 static int oddsizes = 0;
+
 /* use odirect sometimes */
 static int odirect = 0;
 
 /* check contents at startup */
 static int check_initial_files = 0;
+
 /* verify files immediately after writing */
 static int verify_writes = 0;
 
-
 /* -M how much memory we allocate to benchmark allocations */
-static unsigned long mmap_size = 64 * 1024 * 1024;
+static unsigned long mmap_size = 0;
 
 /* these do nothing but spin */
-static int cpu_threads = 24;
+static int cpu_threads = 0;
 
 /* how long we sleep while processing requests */
-static int sleeptime = 10000;
+static int sleeptime = 0;
 
 /* should we use fallocate instead of writing initial file contents */
 static int zallocate = 0;
@@ -463,7 +465,7 @@
 	return ret;
 }
 
-char *option_string = "t:s:C:c:r:n:f:FR:T:m:W:M:w:i:D:oaOVzNIev";
+char *option_string = "t:s:C:c:r:n:f:FR:T:m:W:M:w:i:D:oaOVzNIevU";
 static struct option long_options[] = {
 	{"appendmode", required_argument, 0, 'a'},
 	{"mmapsize", required_argument, 0, 'M'},
@@ -499,22 +501,21 @@
 	fprintf(stderr, "simoop usage:\n"
 		"\t-a (--appendmode): append onto working files\n"
 		"\t-t (--threads): worker threads (def: 16)\n"
-		"\t-m (--memory): memory to allocate during think time in each worker (def 128m)\n"
-		"\t-M (--mmapsize): amount to mmap to time allocator (64M)\n"
+		"\t-m (--memory): memory to allocate during think time in each worker (def 0)\n"
+		"\t-M (--mmapsize): amount to mmap to time allocator (def 0)\n"
 		"\t-r (--runtime): How long to run before exiting (seconds, def: 30)\n"
 		"\t-w (--warmuptime): How long to warmup before resetting the stats (seconds, def: 60)\n"
 		"\t-i (--interval): Sleep time in seconds between latency reports (sec, def: 120\n"
 		"\t-I (--ignorecrcs): don't verify crcs\n"
 		"\t-v (--verify-writes): immediately verify files written (def: no)\n"
 		"\t-V (--verify-startup): Verify all files on startup (def: no)\n"
-		"\t-s (--sleeptime): Sleep time in usecs between worker loops (usec, def: 10000\n"
-		"\t-c (--cputime): How long to think during each worker loop (seconds, def: 3)\n"
-		"\t-C (--cputhreads): How many threads do the cpu time loop (24)\n"
+		"\t-s (--sleeptime): Sleep time in usecs between worker loops (usec, def: 0\n"
+		"\t-c (--cputime): How long to think during each worker loop (seconds, def: 0)\n"
+		"\t-C (--cputhreads): How many threads do the cpu time loop (0)\n"
 		"\t-n (--numfiles): Number of files per directory tree (65536)\n"
 		"\t-f (--filesize): Size of each file (64M)\n"
 		"\t-R (--readsize): amount to read from each file (2M)\n"
 		"\t-W (--writesize): amount to write to tmp files (2M)\n"
-		"\t-T (--rwthreads): how many threads to read/write (8)\n"
 		"\t-D (--duthraeds): how many threads to scanning the working dirs (0)\n"
 		"\t-F (--funksync): fsync sometimes\n"
 		"\t-o (--oddsizes): randomize sizes to unaligned values\n"
@@ -602,9 +603,6 @@
 			write_size = parse_size(optarg);
 			write_size = verify_align_up(write_size);
 			break;
-		case 'T':
-			rw_threads = atoi(optarg);
-			break;
 		case 'D':
 			du_threads = atoi(optarg);
 			break;
@@ -1590,72 +1588,20 @@
 	free(tids);
 }
 
-void *read_thread(void *arg)
+void read_one(char *buf)
 {
-	int i;
-	char *buf = arg;
-
-	for (i = 0; i < 128; i++) {
-		int index = rand() % total_paths;
-		int seq = rand() % num_files;
-		char *path = paths[index];
-		read_from_file(path, seq, buf);
-		if (stopping)
-			break;
-	}
-	return NULL;
+	int index = rand() % total_paths;
+	int seq = rand() % num_files;
+	char *path = paths[index];
+	read_from_file(path, seq, buf);
 }
 
-/* startup reader threads, returns the tids for later waiting */
-void read_some_files(char *buf, pthread_t *tids)
+void write_one(char *buf)
 {
-	unsigned long i;
-	int ret;
-
-	for (i = 0; i < rw_threads; i++) {
-		pthread_t tid;
-		ret = pthread_create(&tid, NULL, read_thread,
-				     buf + i * read_size);
-		if (ret) {
-			fprintf(stderr, "error %d from pthread_create\n", ret);
-			exit(1);
-		}
-		tids[i] = tid;
-	}
-}
-
-void *write_thread(void *arg)
-{
-	char *buf = arg;
-	int i;
-
-	for (i = 0; i < 128; i++) {
-		int index = rand() % total_paths;
-		int seq = rand() % num_files;
-		char *path = paths[index];
-		write_to_file(path, seq, buf);
-		if (stopping)
-			break;
-	}
-	return NULL;
-}
-
-/* startup writer threads, returns the tids for later waiting */
-void write_some_files(char *buf, pthread_t *tids)
-{
-	unsigned long i;
-	int ret;
-
-	for (i = 0; i < rw_threads; i++) {
-		pthread_t tid;
-		ret = pthread_create(&tid, NULL, write_thread,
-				     buf + i * write_size);
-		if (ret) {
-			fprintf(stderr, "error %d from pthread_create\n", ret);
-			exit(1);
-		}
-		tids[i] = tid;
-	}
+	int index = rand() % total_paths;
+	int seq = rand() % num_files;
+	char *path = paths[index];
+	write_to_file(path, seq, buf);
 }
 
 char *aligned_memory_alloc(unsigned long size)
@@ -1695,20 +1641,16 @@
 	char *read_buf = NULL;
 	char *write_buf = NULL;
 	char *mem = NULL;
-	pthread_t *read_tids;
-	pthread_t *write_tids;
 	char *mmap_ptr;
 	int warmup_zerod = 0;
 	unsigned long i;
 
-	read_tids = malloc(sizeof(*read_tids) * rw_threads);
-	write_tids = malloc(sizeof(*write_tids) * rw_threads);
-	if (thinking_mem)
+	if (thinking_mem) {
 		mem = malloc(thinking_mem);
-
-	if (!read_tids || !write_tids || (thinking_mem && !mem)) {
-		perror("allocation failed\n");
-		exit(1);
+		if (!mem) {
+			perror("allocation failed\n");
+			exit(1);
+		}
 	}
 
 	while(!stopping) {
@@ -1721,11 +1663,11 @@
 			warmup_zerod = 1;
 		}
 		if (read_size)
-			read_buf = aligned_memory_alloc(rw_threads * read_size);
+			read_buf = aligned_memory_alloc(read_size);
 		else
 			read_buf = NULL;
 		if (write_size)
-			write_buf = aligned_memory_alloc(rw_threads * write_size);
+			write_buf = aligned_memory_alloc(write_size);
 		else
 			write_buf = NULL;
 
@@ -1733,19 +1675,10 @@
 		if (thinking_mem)
 			memset(mem, 0, thinking_mem);
 
-		gettimeofday(&start, NULL);
-
 		/* Start the threads to read files */
 		if (read_size) {
-			read_some_files(read_buf, read_tids);
-
-			/* think in parallel */
-			usec_spin(cputime);
-
-			/* wait for our reads to finish */
-			for (i = 0; i < rw_threads; i++) {
-				pthread_join(read_tids[i], NULL);
-			}
+			gettimeofday(&start, NULL);
+			read_one(read_buf);
 			gettimeofday(&now, NULL);
 
 			/*
@@ -1759,10 +1692,7 @@
 		/* write out the (pretend) results */
 		if (write_size) {
 			gettimeofday(&start, NULL);
-			write_some_files(write_buf, write_tids);
-			for (i = 0; i < rw_threads; i++) {
-				pthread_join(write_tids[i], NULL);
-			}
+			write_one(write_buf);
 			gettimeofday(&now, NULL);
 			record_one_lat(&td->stats[WRITE_STATS], &start, &now);
 		}
@@ -1796,8 +1726,8 @@
 		}
 		usec_spin(cputime);
 
-		aligned_memory_free(read_buf, rw_threads * read_size);
-		aligned_memory_free(write_buf, rw_threads * write_size);
+		aligned_memory_free(read_buf, read_size);
+		aligned_memory_free(write_buf, write_size);
 		td->work_done++;
 
 		if (sleeptime)
@@ -1805,8 +1735,6 @@
 	}
 
 	free(mem);
-	free(read_tids);
-	free(write_tids);
 	return NULL;
 }
 
@@ -1897,7 +1825,7 @@
 	for (i = 0; i < TOTAL_STATS; i++) {
 		unsigned int p50 = 0, p95 = 0, p99 = 0;
 		calc_p99(&dest[i], &p50, &p95, &p99);
-		printf("%s (p50: %'d) (p95: %'d) (p99: %'d)\n",
+		printf("%s usec: (p50: %'d) (p95: %'d) (p99: %'d)\n",
 		       stat_labels[i], p50, p95, p99);
 	}
 }