#include #include #include #include extern "C" { #include #include #include #include } #include #include #include "../benchcltr.hfa" int fd; volatile bool run = false; volatile size_t count = 0; unsigned long int buflen = 50; void * reader_main( void * arg ) { pthread_barrier_wait( (pthread_barrier_t*) arg ); /* paranoid */ assert( true == __atomic_load_n(&run, __ATOMIC_RELAXED) ); char data[buflen]; struct iovec iov = { data, buflen }; while(__atomic_load_n(&run, __ATOMIC_RELAXED)) { int r = preadv2(fd, &iov, 1, 0, 0); if(r < 0) { fprintf(stderr, "%s\n", strerror(-r)); abort(); } __atomic_fetch_add( &count, 1, __ATOMIC_SEQ_CST ); } return NULL; } int main(int argc, char * argv[]) { unsigned flags = 0; unsigned sublen = 16; setlocale(LC_ALL, ""); for(;;) { static struct option options[] = { BENCH_OPT_LONG {"polled-io", required_argument, 0, 'i'}, {"bufsize", required_argument, 0, 'b'}, {0, 0, 0, 0} }; int idx = 0; int opt = getopt_long(argc, argv, BENCH_OPT_SHORT "ib:", options, &idx); const char * arg = optarg ? optarg : ""; char * end; switch(opt) { // Exit Case case -1: goto arg_loop; BENCH_OPT_CASE case 'i': flags |= O_DIRECT; break; case 'b': buflen = strtoul(arg, &end, 10); if(*end != '\0' && buflen < 10) { fprintf(stderr, "Buffer size must be at least 10, was %s\n", arg); goto usage; } break; default: /* ? */ fprintf(stderr, "%d\n", opt); usage: bench_usage( argv ); fprintf( stderr, " -i, --polled-io If set opens the file with O_DIRECT\n" ); fprintf( stderr, " -b, --buflen=SIZE Number of bytes to read per request\n" ); exit(EXIT_FAILURE); } } arg_loop: fd = open(__FILE__, flags); if(fd < 0) { fprintf(stderr, "Could not open source file\n"); exit(EXIT_FAILURE); } printf("Running %d threads, reading %lu bytes each, over %d processors for %f seconds\n", nthreads, buflen, nprocs, duration); { uint64_t start, end; { pthread_barrier_t barrier; pthread_barrier_init(&barrier, NULL, nthreads + 1); { pthread_t threads[nthreads]; for(int i = 0; i < nthreads; i++) { pthread_attr_t attr; pthread_attr_init( &attr ); pthread_create( &threads[i], &attr, reader_main, &barrier ); } printf("Starting\n"); bool is_tty = isatty(STDOUT_FILENO); start = timeHiRes(); run = true; pthread_barrier_wait( &barrier ); wait_duration(duration, start, end, is_tty); run = false; end = timeHiRes(); printf("\nDone\n"); for(int i = 0; i < nthreads; i++) { void * ret; pthread_join( threads[i], &ret ); } } pthread_barrier_destroy(&barrier); } printf("Took %'ld ms\n", to_miliseconds(end - start)); printf("Total reads : %'15zu\n", count); printf("Reads per second : %'18.2lf\n", ((double)count) / to_fseconds(end - start)); printf("Total read size : %'15zu\n", buflen * count); printf("Bytes per second : %'18.2lf\n", ((double)count * buflen) / to_fseconds(end - start)); } close(fd); }