X-Git-Url: http://git.vrable.net/?a=blobdiff_plain;f=microbench%2Fmixedbench.c;h=475542496862a1a5f08ff4060447988376815a4a;hb=78f5b7a9c7840ce8b2dffb13fca676a18f8f9eb4;hp=81e63cfdcdc69eaf8cc5326ec26e5a16f0fca45b;hpb=52331b779901433d07c8c51b620261ffd4bebcd9;p=bluesky.git diff --git a/microbench/mixedbench.c b/microbench/mixedbench.c index 81e63cf..4755424 100644 --- a/microbench/mixedbench.c +++ b/microbench/mixedbench.c @@ -9,6 +9,9 @@ * Threads * Benchmark duration (seconds) * Target operations per second (aggregate across all threads) + * Interval count (how many times to report results during the run) + * Directory size (number of files per numbered subdirectory) + * Read/write block size (0 for the entire file) */ #include @@ -24,9 +27,11 @@ #include #include -int opt_filesize, opt_filecount, opt_threads, opt_duration; +int opt_filesize, opt_filecount, opt_threads, opt_duration, opt_intervals, opt_dirsize, opt_blocksize; double opt_writeratio, opt_ops; +int write_threads; + struct thread_state { pthread_t thread; pthread_mutex_t lock; @@ -88,21 +93,52 @@ void benchmark_op(struct thread_state *ts) start = now_hires(); - char filename[64]; - sprintf(filename, "t%d/%d", ts->thread_num, get_random(opt_filecount)); + /* The space of all files is partitioned evenly based on the number of + * threads. Pick a file out of our particular partition. */ + int thread_num, thread_count; + if (ts->thread_num >= write_threads) { + /* Read */ + thread_num = ts->thread_num - write_threads; + thread_count = opt_threads - write_threads; + } else { + /* Write */ + thread_num = ts->thread_num; + thread_count = write_threads; + } - double r = get_random(1000000) / 1e6; + int n = get_random(opt_filecount / thread_count); + n += thread_num * (opt_filecount / thread_count); + int n1 = n / opt_dirsize, n2 = n % opt_dirsize; + char filename[256]; + sprintf(filename, "%d/%d", n1, n2); + + /* If a smaller blocksize was requested, choose a random offset within the + * file to use. */ + int offset = 0; + if (opt_blocksize > 0) { + offset = get_random(opt_filesize / opt_blocksize) * opt_blocksize; + } - if (r >= opt_writeratio) { + if (ts->thread_num >= write_threads) { /* Read */ FILE *f = fopen(filename, "rb"); if (f == NULL) { - perror("fopen"); + fprintf(stderr, "fopen(%s): %m\n", filename); return; } + if (offset != 0) + fseek(f, offset, SEEK_SET); + char buf[65536]; - while (fread(buf, 1, sizeof(buf), f) > 0) { } + int bytes_left = opt_blocksize > 0 ? opt_blocksize : opt_filesize; + while (bytes_left > 0) { + size_t read = fread(buf, 1, bytes_left < sizeof(buf) + ? bytes_left : sizeof(buf), f); + if (ferror(f)) + return; + bytes_left -= read; + } fclose(f); end = now_hires(); @@ -113,14 +149,17 @@ void benchmark_op(struct thread_state *ts) pthread_mutex_unlock(&ts->lock); } else { /* Write */ - FILE *f = fopen(filename, "wb"); + FILE *f = fopen(filename, "r+b"); if (f == NULL) { - perror("fopen"); + fprintf(stderr, "fopen(%s): %m\n", filename); return; } + if (offset != 0) + fseek(f, offset, SEEK_SET); + char buf[65536]; - int bytes_left = opt_filesize; + int bytes_left = opt_blocksize > 0 ? opt_blocksize : opt_filesize; while (bytes_left > 0) { size_t written = fwrite(buf, 1, bytes_left < sizeof(buf) @@ -192,6 +231,7 @@ void reset_stats(int print, double duration) write_time2 += threads[i].write_time2; threads[i].read_count = threads[i].write_count = 0; threads[i].read_time = threads[i].write_time = 0; + threads[i].read_time2 = threads[i].write_time2 = 0; pthread_mutex_unlock(&threads[i].lock); } @@ -203,12 +243,13 @@ void reset_stats(int print, double duration) write_count / duration, write_time / write_count, stddev(write_time, write_time2, write_count)); printf("\n"); + fflush(stdout); } } int main(int argc, char *argv[]) { - if (argc != 7) { + if (argc != 10) { fprintf(stderr, "Usage: TODO\n"); return 1; } @@ -219,18 +260,27 @@ int main(int argc, char *argv[]) opt_threads = atoi(argv[4]); opt_duration = atoi(argv[5]); opt_ops = atof(argv[6]); + opt_intervals = atoi(argv[7]); + opt_dirsize = atoi(argv[8]); + opt_blocksize = atoi(argv[9]); srandom(time(NULL)); start_time = now_hires(); + /* Partition threads into those that should do reads and those for writes, + * as close as possible to the desired allocation. */ + write_threads = (int)round(opt_threads * opt_writeratio); + fprintf(stderr, "Using %d threads for reads, %d for writes\n", + opt_threads - write_threads, write_threads); + for (int i = 0; i < opt_threads; i++) { launch_thread(i); } - for (int i = 0; i < 4; i++) { - sleep_micros(opt_duration * 1000000 / 4); - reset_stats(1, opt_duration / 4.0); + for (int i = 0; i < opt_intervals; i++) { + sleep_micros(opt_duration * 1000000 / opt_intervals); + reset_stats(1, (double)opt_duration / opt_intervals); } return 0;