summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Mason <clm@fb.com>2020-06-18 16:58:43 -0700
committerChris Mason <clm@fb.com>2020-06-18 16:58:43 -0700
commitbb1adec78e2255dc97031906bd3140b53dfe6df8 (patch)
tree134de12082abfc4c2ae75f0d436fe47cd6b1d995
parent17703d4fdf13ca5a3284c796033a1146915bede7 (diff)
downloadsimoop-bb1adec78e2255dc97031906bd3140b53dfe6df8.tar.gz
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>
-rw-r--r--simoop.c148
1 files changed, 38 insertions, 110 deletions
diff --git a/simoop.c b/simoop.c
index f73bb64..193330f 100644
--- a/simoop.c
+++ b/simoop.c
@@ -66,7 +66,7 @@ static int worker_threads = 16;
/* -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 num_files = 65536;
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 @@ static unsigned long thinking_mem = 128 * 1024 * 1024UL;
/* 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 @@ unsigned long long parse_size(char *s)
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 @@ static void print_usage(void)
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 @@ static void parse_options(int ac, char **av)
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 @@ void run_filler_threads(void)
free(tids);
}
-void *read_thread(void *arg)
-{
- 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;
-}
-
-/* startup reader threads, returns the tids for later waiting */
-void read_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, 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)
+void read_one(char *buf)
{
- 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;
+ int index = rand() % total_paths;
+ int seq = rand() % num_files;
+ char *path = paths[index];
+ read_from_file(path, seq, buf);
}
-/* startup writer threads, returns the tids for later waiting */
-void write_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, 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 @@ void *worker_thread(void *arg)
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 @@ void *worker_thread(void *arg)
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 @@ void *worker_thread(void *arg)
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 @@ void *worker_thread(void *arg)
/* 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 @@ void *worker_thread(void *arg)
}
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 @@ void *worker_thread(void *arg)
}
free(mem);
- free(read_tids);
- free(write_tids);
return NULL;
}
@@ -1897,7 +1825,7 @@ static void collect_stats(struct stats *dest, struct thread_data *worker_threads
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);
}
}