| [5847d35] | 1 | #include <stdlib.h> | 
|---|
|  | 2 | #include <stdio.h> | 
|---|
|  | 3 | #include <string.h> | 
|---|
|  | 4 |  | 
|---|
|  | 5 | extern "C" { | 
|---|
|  | 6 | #include <locale.h> | 
|---|
|  | 7 | #include <getopt.h> | 
|---|
|  | 8 | #include <fcntl.h> | 
|---|
|  | 9 | #include <sys/uio.h> | 
|---|
|  | 10 | } | 
|---|
|  | 11 |  | 
|---|
|  | 12 | #include <unistd.h> | 
|---|
|  | 13 |  | 
|---|
|  | 14 | #include <clock.hfa> | 
|---|
|  | 15 | #include <kernel.hfa> | 
|---|
|  | 16 | #include <thread.hfa> | 
|---|
|  | 17 | #include <time.hfa> | 
|---|
|  | 18 |  | 
|---|
| [1bcdeff] | 19 | extern bool traceHeapOn(); | 
|---|
| [2489d31] | 20 | extern ssize_t cfa_preadv2(int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags); | 
|---|
| [5847d35] | 21 |  | 
|---|
|  | 22 | int fd; | 
|---|
|  | 23 | volatile bool run = false; | 
|---|
|  | 24 | volatile size_t count = 0; | 
|---|
|  | 25 |  | 
|---|
|  | 26 | unsigned long int buflen = 50; | 
|---|
|  | 27 |  | 
|---|
| [4069faad] | 28 | cluster * the_cluster; | 
|---|
|  | 29 |  | 
|---|
| [5847d35] | 30 | thread Reader {}; | 
|---|
| [4069faad] | 31 | void ?{}( Reader & this ) { | 
|---|
|  | 32 | ((thread&)this){ "Reader Thread", *the_cluster }; | 
|---|
|  | 33 | } | 
|---|
|  | 34 |  | 
|---|
|  | 35 | struct my_processor { | 
|---|
|  | 36 | processor p; | 
|---|
|  | 37 | }; | 
|---|
|  | 38 |  | 
|---|
|  | 39 | void ?{}( my_processor & this ) { | 
|---|
|  | 40 | (this.p){ "I/O Processor", *the_cluster }; | 
|---|
|  | 41 | } | 
|---|
|  | 42 |  | 
|---|
| [5847d35] | 43 | void main( Reader & ) { | 
|---|
|  | 44 | while(!__atomic_load_n(&run, __ATOMIC_RELAXED)) yield(); | 
|---|
|  | 45 |  | 
|---|
|  | 46 | char data[buflen]; | 
|---|
|  | 47 | struct iovec iov = { data, buflen }; | 
|---|
|  | 48 |  | 
|---|
|  | 49 | while(__atomic_load_n(&run, __ATOMIC_RELAXED)) { | 
|---|
| [4069faad] | 50 | int r = cfa_preadv2(fd, &iov, 1, 0, 0); | 
|---|
| [b1ac7dd] | 51 | if(r < 0) abort("%s\n", strerror(-r)); | 
|---|
| [4069faad] | 52 |  | 
|---|
| [5847d35] | 53 | __atomic_fetch_add( &count, 1, __ATOMIC_SEQ_CST ); | 
|---|
|  | 54 | } | 
|---|
|  | 55 | } | 
|---|
|  | 56 |  | 
|---|
|  | 57 | int main(int argc, char * argv[]) { | 
|---|
|  | 58 | double duration   = 5.0; | 
|---|
|  | 59 | unsigned long int nthreads = 2; | 
|---|
|  | 60 | unsigned long int nprocs   = 1; | 
|---|
| [dd4e2d7] | 61 | unsigned flags = 0; | 
|---|
|  | 62 | unsigned sublen = 16; | 
|---|
| [5847d35] | 63 |  | 
|---|
|  | 64 | arg_loop: | 
|---|
|  | 65 | for(;;) { | 
|---|
|  | 66 | static struct option options[] = { | 
|---|
| [0335620] | 67 | {"duration",     required_argument, 0, 'd'}, | 
|---|
|  | 68 | {"nthreads",     required_argument, 0, 't'}, | 
|---|
|  | 69 | {"nprocs",       required_argument, 0, 'p'}, | 
|---|
|  | 70 | {"bufsize",      required_argument, 0, 'b'}, | 
|---|
|  | 71 | {"userthread",   no_argument      , 0, 'u'}, | 
|---|
|  | 72 | {"submitthread", no_argument      , 0, 's'}, | 
|---|
| [dd4e2d7] | 73 | {"submitlength", required_argument, 0, 'l'}, | 
|---|
| [5847d35] | 74 | {0, 0, 0, 0} | 
|---|
|  | 75 | }; | 
|---|
|  | 76 |  | 
|---|
|  | 77 | int idx = 0; | 
|---|
| [dd4e2d7] | 78 | int opt = getopt_long(argc, argv, "d:t:p:b:usl:", options, &idx); | 
|---|
| [5847d35] | 79 |  | 
|---|
|  | 80 | const char * arg = optarg ? optarg : ""; | 
|---|
|  | 81 | char * end; | 
|---|
|  | 82 | switch(opt) { | 
|---|
|  | 83 | // Exit Case | 
|---|
|  | 84 | case -1: | 
|---|
|  | 85 | break arg_loop; | 
|---|
|  | 86 | // Numeric Arguments | 
|---|
|  | 87 | case 'd': | 
|---|
|  | 88 | duration = strtod(arg, &end); | 
|---|
|  | 89 | if(*end != '\0') { | 
|---|
|  | 90 | fprintf(stderr, "Duration must be a valid double, was %s\n", arg); | 
|---|
|  | 91 | goto usage; | 
|---|
|  | 92 | } | 
|---|
|  | 93 | break; | 
|---|
|  | 94 | case 't': | 
|---|
|  | 95 | nthreads = strtoul(arg, &end, 10); | 
|---|
| [1bcdeff] | 96 | if(*end != '\0' || nthreads < 1) { | 
|---|
| [5847d35] | 97 | fprintf(stderr, "Number of threads must be a positive integer, was %s\n", arg); | 
|---|
|  | 98 | goto usage; | 
|---|
|  | 99 | } | 
|---|
|  | 100 | break; | 
|---|
|  | 101 | case 'p': | 
|---|
|  | 102 | nprocs = strtoul(arg, &end, 10); | 
|---|
| [1bcdeff] | 103 | if(*end != '\0' || nprocs < 1) { | 
|---|
| [5847d35] | 104 | fprintf(stderr, "Number of processors must be a positive integer, was %s\n", arg); | 
|---|
|  | 105 | goto usage; | 
|---|
|  | 106 | } | 
|---|
|  | 107 | break; | 
|---|
|  | 108 | case 'b': | 
|---|
|  | 109 | buflen = strtoul(arg, &end, 10); | 
|---|
|  | 110 | if(*end != '\0' && buflen < 10) { | 
|---|
|  | 111 | fprintf(stderr, "Buffer size must be at least 10, was %s\n", arg); | 
|---|
|  | 112 | goto usage; | 
|---|
|  | 113 | } | 
|---|
|  | 114 | break; | 
|---|
| [b6f2b213] | 115 | case 'u': | 
|---|
|  | 116 | flags |= CFA_CLUSTER_IO_POLLER_USER_THREAD; | 
|---|
|  | 117 | break; | 
|---|
| [0335620] | 118 | case 's': | 
|---|
|  | 119 | flags |= CFA_CLUSTER_IO_POLLER_THREAD_SUBMITS; | 
|---|
|  | 120 | break; | 
|---|
| [dd4e2d7] | 121 | case 'l': | 
|---|
|  | 122 | sublen = strtoul(arg, &end, 10); | 
|---|
|  | 123 | if(*end != '\0' && sublen < 16) { | 
|---|
|  | 124 | fprintf(stderr, "Submit length must be at least 16, was %s\n", arg); | 
|---|
|  | 125 | goto usage; | 
|---|
|  | 126 | } | 
|---|
|  | 127 | flags |= (sublen << CFA_CLUSTER_IO_BUFFLEN_OFFSET); | 
|---|
|  | 128 | break; | 
|---|
| [5847d35] | 129 | // Other cases | 
|---|
|  | 130 | default: /* ? */ | 
|---|
|  | 131 | fprintf(stderr, "%d\n", opt); | 
|---|
|  | 132 | usage: | 
|---|
|  | 133 | fprintf(stderr, "Usage: %s : [options]\n", argv[0]); | 
|---|
|  | 134 | fprintf(stderr, "\n"); | 
|---|
|  | 135 | fprintf(stderr, "  -d, --duration=DURATION  Duration of the experiment, in seconds\n"); | 
|---|
|  | 136 | fprintf(stderr, "  -t, --nthreads=NTHREADS  Number of user threads\n"); | 
|---|
|  | 137 | fprintf(stderr, "  -p, --nprocs=NPROCS      Number of kernel threads\n"); | 
|---|
|  | 138 | fprintf(stderr, "  -b, --buflen=SIZE        Number of bytes to read per request\n"); | 
|---|
| [0335620] | 139 | fprintf(stderr, "  -u, --userthread         If set, cluster uses user-thread to poll I/O\n"); | 
|---|
|  | 140 | fprintf(stderr, "  -s, --submitthread       If set, cluster uses polling thread to submit I/O\n"); | 
|---|
| [5847d35] | 141 | exit(EXIT_FAILURE); | 
|---|
|  | 142 | } | 
|---|
|  | 143 | } | 
|---|
|  | 144 |  | 
|---|
| [4069faad] | 145 | fd = open(__FILE__, 0); | 
|---|
| [5847d35] | 146 | if(fd < 0) { | 
|---|
|  | 147 | fprintf(stderr, "Could not open source file\n"); | 
|---|
|  | 148 | exit(EXIT_FAILURE); | 
|---|
|  | 149 | } | 
|---|
|  | 150 |  | 
|---|
| [cbabfd4] | 151 | printf("Running %lu threads, reading %lu bytes each, over %lu processors for %lf seconds\n", nthreads, buflen, nprocs, duration); | 
|---|
| [5847d35] | 152 |  | 
|---|
|  | 153 | { | 
|---|
| [4069faad] | 154 | Time start, end; | 
|---|
| [b6f2b213] | 155 | cluster cl = { "IO Cluster", flags }; | 
|---|
| [4069faad] | 156 | the_cluster = &cl; | 
|---|
|  | 157 | #if !defined(__CFA_NO_STATISTICS__) | 
|---|
|  | 158 | print_stats_at_exit( cl ); | 
|---|
|  | 159 | #endif | 
|---|
| [5847d35] | 160 | { | 
|---|
| [4069faad] | 161 | my_processor procs[nprocs]; | 
|---|
|  | 162 | { | 
|---|
|  | 163 | Reader threads[nthreads]; | 
|---|
|  | 164 |  | 
|---|
|  | 165 | printf("Starting\n"); | 
|---|
|  | 166 | start = getTime(); | 
|---|
|  | 167 | run = true; | 
|---|
|  | 168 | do { | 
|---|
|  | 169 | sleep(500`ms); | 
|---|
|  | 170 | end = getTime(); | 
|---|
|  | 171 | } while( (end - start) < duration`s ); | 
|---|
|  | 172 | run = false; | 
|---|
| [5847d35] | 173 | end = getTime(); | 
|---|
| [4069faad] | 174 | printf("Done\n"); | 
|---|
|  | 175 | } | 
|---|
| [5847d35] | 176 | } | 
|---|
| [b1ac7dd] | 177 | printf("Took %'ld ms\n", (end - start)`ms); | 
|---|
| [cbabfd4] | 178 | printf("Total reads      : %'15zu\n", count); | 
|---|
|  | 179 | printf("Reads per second : %'18.2lf\n", ((double)count) / (end - start)`s); | 
|---|
|  | 180 | printf("Total read size  : %'15zu\n", buflen * count); | 
|---|
|  | 181 | printf("Bytes per second : %'18.2lf\n", ((double)count * buflen) / (end - start)`s); | 
|---|
| [5847d35] | 182 | } | 
|---|
|  | 183 |  | 
|---|
|  | 184 | close(fd); | 
|---|
|  | 185 | } | 
|---|