From: Michael Vrable Date: Mon, 7 Feb 2011 18:02:04 +0000 (-0800) Subject: A few more updates to the mixed read/write microbenchmark. X-Git-Url: http://git.vrable.net/?p=bluesky.git;a=commitdiff_plain;h=52331b779901433d07c8c51b620261ffd4bebcd9 A few more updates to the mixed read/write microbenchmark. --- diff --git a/microbench/CMakeLists.txt b/microbench/CMakeLists.txt index 33b4bd7..5a6a45f 100644 --- a/microbench/CMakeLists.txt +++ b/microbench/CMakeLists.txt @@ -8,7 +8,7 @@ add_executable(statbench statbench.c) target_link_libraries(statbench pthread rt) add_executable(mixedbench mixedbench.c) -target_link_libraries(mixedbench pthread rt) +target_link_libraries(mixedbench pthread rt m) add_executable(lockmem lockmem.c) diff --git a/microbench/mixedbench.c b/microbench/mixedbench.c index ae26e71..81e63cf 100644 --- a/microbench/mixedbench.c +++ b/microbench/mixedbench.c @@ -8,6 +8,7 @@ * Write fraction (0.0 - 1.0) * Threads * Benchmark duration (seconds) + * Target operations per second (aggregate across all threads) */ #include @@ -21,16 +22,17 @@ #include #include #include +#include int opt_filesize, opt_filecount, opt_threads, opt_duration; -double opt_writeratio; +double opt_writeratio, opt_ops; struct thread_state { pthread_t thread; pthread_mutex_t lock; int thread_num; int read_count, write_count; - int64_t read_time, write_time; + double read_time, write_time, read_time2, write_time2; }; static int64_t start_time; @@ -38,6 +40,18 @@ static int64_t start_time; #define MAX_THREADS 128 struct thread_state threads[MAX_THREADS]; +static double sq(double x) +{ + return x * x; +} + +static double stddev(double x, double x2, int n) +{ + if (n < 2) + return 0; + return sqrt((x2 / n - sq(x / n)) * n / (n - 1)); +} + int64_t now_hires() { struct timespec time; @@ -68,28 +82,6 @@ void sleep_micros(int duration) ; } -#if 0 -void bench_write() -{ - FILE *f = fopen("writetest", "wb"); - if (f == NULL) { - perror("fopen"); - return; - } - - char buf[4096]; - for (int i = 0; i < 16; i++) { - int64_t start, end; - start = now_hires(); - rewind(f); - fwrite(buf, 1, sizeof(buf), f); - fflush(f); - end = now_hires(); - printf("Pass %d: Time = %"PRIi64"\n", i, end - start); - } -} -#endif - void benchmark_op(struct thread_state *ts) { int64_t start, end; @@ -116,7 +108,8 @@ void benchmark_op(struct thread_state *ts) end = now_hires(); pthread_mutex_lock(&ts->lock); ts->read_count++; - ts->read_time += (end - start); + ts->read_time += (end - start) / 1e9; + ts->read_time2 += sq((end - start) / 1e9); pthread_mutex_unlock(&ts->lock); } else { /* Write */ @@ -142,7 +135,8 @@ void benchmark_op(struct thread_state *ts) end = now_hires(); pthread_mutex_lock(&ts->lock); ts->write_count++; - ts->write_time += (end - start); + ts->write_time += (end - start) / 1e9; + ts->write_time2 += sq((end - start) / 1e9); pthread_mutex_unlock(&ts->lock); } } @@ -151,9 +145,16 @@ void *benchmark_thread(void *arg) { struct thread_state *ts = (struct thread_state *)arg; + int target_delay = (opt_threads / opt_ops) * 1e6; + while (1) { + int64_t start = now_hires(); benchmark_op(ts); - //sleep_micros(100000); + int64_t end = now_hires(); + + int elapsed = (end - start) / 1000; + if (elapsed < target_delay) + sleep_micros(target_delay - elapsed); } return NULL; @@ -164,7 +165,6 @@ void launch_thread(int i) memset(&threads[i], 0, sizeof(struct thread_state)); threads[i].thread_num = i; pthread_mutex_init(&threads[i].lock, NULL); - printf("Launching thread %d...\n", i); if (pthread_create(&threads[i].thread, NULL, benchmark_thread, &threads[i]) != 0) { fprintf(stderr, "Error launching thread!\n"); exit(1); @@ -177,10 +177,10 @@ void wait_thread(int n) pthread_join(threads[n].thread, &result); } -void reset_stats(int print) +void reset_stats(int print, double duration) { int read_count = 0, write_count = 0; - int64_t read_time = 0, write_time = 0; + double read_time = 0, write_time = 0, read_time2 = 0, write_time2 = 0; for (int i = 0; i < opt_threads; i++) { pthread_mutex_lock(&threads[i].lock); @@ -188,23 +188,27 @@ void reset_stats(int print) write_count += threads[i].write_count; read_time += threads[i].read_time; write_time += threads[i].write_time; + read_time2 += threads[i].read_time2; + write_time2 += threads[i].write_time2; threads[i].read_count = threads[i].write_count = 0; threads[i].read_time = threads[i].write_time = 0; pthread_mutex_unlock(&threads[i].lock); } if (print) { - printf("read: [%d, %f]\n", - read_count, read_time / 1e9 / read_count); - printf("write: [%d, %f]\n", - write_count, write_time / 1e9 / write_count); + printf("read: [%g, %f, %f]\n", + read_count / duration, read_time / read_count, + stddev(read_time, read_time2, read_count)); + printf("write: [%g, %f, %f]\n", + write_count / duration, write_time / write_count, + stddev(write_time, write_time2, write_count)); printf("\n"); } } int main(int argc, char *argv[]) { - if (argc != 6) { + if (argc != 7) { fprintf(stderr, "Usage: TODO\n"); return 1; } @@ -214,11 +218,11 @@ int main(int argc, char *argv[]) opt_writeratio = atof(argv[3]); opt_threads = atoi(argv[4]); opt_duration = atoi(argv[5]); + opt_ops = atof(argv[6]); srandom(time(NULL)); start_time = now_hires(); - printf("Testing with %d threads\n", opt_threads); for (int i = 0; i < opt_threads; i++) { launch_thread(i); @@ -226,7 +230,7 @@ int main(int argc, char *argv[]) for (int i = 0; i < 4; i++) { sleep_micros(opt_duration * 1000000 / 4); - reset_stats(1); + reset_stats(1, opt_duration / 4.0); } return 0;