#include #include #include extern "C" { #include #include #include #include } #include #include #include #include #include #if !defined(HAVE_LINUX_IO_URING_H) #warning no io uring #endif extern bool traceHeapOn(); extern ssize_t cfa_preadv2(int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags); int fd; volatile bool run = false; volatile size_t count = 0; unsigned long int buflen = 50; thread Reader {}; void main( Reader & ) { while(!__atomic_load_n(&run, __ATOMIC_RELAXED)) yield(); char data[buflen]; struct iovec iov = { data, buflen }; while(__atomic_load_n(&run, __ATOMIC_RELAXED)) { cfa_preadv2(fd, &iov, 1, 0, 0); __atomic_fetch_add( &count, 1, __ATOMIC_SEQ_CST ); } } int main(int argc, char * argv[]) { #if !defined(__CFA_NO_STATISTICS__) print_stats_at_exit( *active_cluster() ); #endif double duration = 5.0; unsigned long int nthreads = 2; unsigned long int nprocs = 1; printf("Setting local\n"); setlocale(LC_NUMERIC, ""); arg_loop: for(;;) { static struct option options[] = { {"duration", required_argument, 0, 'd'}, {"nthreads", required_argument, 0, 't'}, {"nprocs", required_argument, 0, 'p'}, {"bufsize", required_argument, 0, 'b'}, {0, 0, 0, 0} }; int idx = 0; int opt = getopt_long(argc, argv, "d:t:p:b:", options, &idx); const char * arg = optarg ? optarg : ""; char * end; switch(opt) { // Exit Case case -1: break arg_loop; // Numeric Arguments case 'd': duration = strtod(arg, &end); if(*end != '\0') { fprintf(stderr, "Duration must be a valid double, was %s\n", arg); goto usage; } break; case 't': nthreads = strtoul(arg, &end, 10); if(*end != '\0' || nthreads < 1) { fprintf(stderr, "Number of threads must be a positive integer, was %s\n", arg); goto usage; } break; case 'p': nprocs = strtoul(arg, &end, 10); if(*end != '\0' || nprocs < 1) { fprintf(stderr, "Number of processors must be a positive integer, was %s\n", arg); goto usage; } 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; // Other cases default: /* ? */ fprintf(stderr, "%d\n", opt); usage: fprintf(stderr, "Usage: %s : [options]\n", argv[0]); fprintf(stderr, "\n"); fprintf(stderr, " -d, --duration=DURATION Duration of the experiment, in seconds\n"); fprintf(stderr, " -t, --nthreads=NTHREADS Number of user threads\n"); fprintf(stderr, " -p, --nprocs=NPROCS Number of kernel threads\n"); fprintf(stderr, " -b, --buflen=SIZE Number of bytes to read per request\n"); exit(EXIT_FAILURE); } } int fd = open(__FILE__, 0); if(fd < 0) { fprintf(stderr, "Could not open source file\n"); exit(EXIT_FAILURE); } printf("Running %lu threads over %lu processors for %lf seconds\n", nthreads, nprocs, duration); Time start, end; { processor procs[nprocs - 1]; { Reader threads[nthreads]; printf("Starting\n"); start = getTime(); run = true; do { sleep(500`ms); end = getTime(); } while( (end - start) < duration`s ); run = false; end = getTime(); } } printf("Took %ld ms\n", (end - start)`ms); printf("Total reads: %'zu\n", count); printf("Reads per second: %'lf\n", ((double)count) / (end - start)`s); close(fd); printf("Done\n"); }