#define _POSIX_C_SOURCE 200809L #include #include #include #include #include #include #include #include #include "../ipc.h" typedef struct Key Key; struct Key { int k; int mod; }; static Key *keys; static size_t nkeys; static int fd; static void die(char *msg) { perror(msg); exit(1); } static void addkey(int k, int mod) { static size_t cap; Key *p; if(nkeys >= cap){ if(cap > SIZE_MAX / 2 / sizeof(Key)){ fprintf(stderr, "too many keys\n"); exit(1); } cap = cap ? cap * 2 : 256; p = realloc(keys, cap * sizeof(Key)); if(!p) die("realloc"); keys = p; } keys[nkeys].k = k; keys[nkeys].mod = mod; nkeys++; } static void loadkeys(char *file) { FILE *f; int c; f = fopen(file, "r"); if(!f) die(file); while((c = fgetc(f)) != EOF){ if(c == '\n' || c == '\r') continue; if(c != '^'){ addkey(c, 0); continue; } c = fgetc(f); if(c == EOF) break; switch(c){ case 'B': addkey(Kback, 0); break; case 'R': addkey(Kret, 0); break; case 'E': addkey(Kesc, 0); break; default: addkey(c, Mctrl); break; } } fclose(f); if(nkeys == 0){ fprintf(stderr, "%s: no keys\n", file); exit(1); } } static uint64_t iterations(char *s) { uintmax_t n; char *end; if(*s == '\0' || *s == '-') goto Bad; errno = 0; n = strtoumax(s, &end, 10); if(errno != 0 || *end != '\0' || n == 0 || n > UINT64_MAX) goto Bad; return n; Bad: fprintf(stderr, "invalid iteration count: %s\n", s); exit(1); } static void dial(void) { fd = ipcconnect(); if(fd < 0) die("connect"); } static void sendkey(int key, int mod) { unsigned char req[Ipcreqsz]; ipcpackreq(req, 0, mod, key); if(ipcsend(fd, req, sizeof req) < 0) die("write"); } static int readresp(void) { char buf[Ipcfieldmax+1]; Ipcresp resp; return ipcreadresp(fd, 0, buf, sizeof buf, NULL, 0, &resp); } static double now(void) { struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); return ts.tv_sec + ts.tv_nsec * 1e-9; } int main(int argc, char **argv) { size_t j; uint64_t i, niter, total; double t0, t1, dt; if(argc != 2 && argc != 3){ fprintf(stderr, "usage: bench file [niter]\n"); exit(1); } loadkeys(argv[1]); niter = argc == 3 ? iterations(argv[2]) : 1000; if(nkeys > UINT64_MAX || niter > UINT64_MAX / nkeys){ fprintf(stderr, "iteration count overflows key total\n"); exit(1); } total = niter * nkeys; dial(); t0 = now(); for(i = 0; i < niter; i++) for(j = 0; j < nkeys; j++){ sendkey(keys[j].k, keys[j].mod); if(readresp() < 0){ fprintf(stderr, "failed at iter %" PRIu64 " key %zu\n", i, j); exit(1); } } t1 = now(); dt = t1 - t0; printf("%" PRIu64 " iters x %zu keys = %" PRIu64 " keys\n", niter, nkeys, total); printf("%.3f ms total, %.3f us/key, %.3f us/iter\n", dt * 1000, dt * 1e6 / total, dt * 1e6 / niter); close(fd); return 0; }