#include #include #include #include #include #include #include #include #include #define N 5 typedef struct { double time; size_t nread; } resultT; int cmptime(const void *a, const void *b) { const resultT *aa = a, *bb = b; if (aa->time < bb->time) { return -1; } else if (aa->time > bb->time) { return +1; } else { return 0; } } resultT median (resultT *v, int n) { // n is small, keep it simple qsort(v, n, sizeof(*v), cmptime); return v[n / 2]; } int main(int argc, char **argv) { resultT **results = calloc(sizeof(*results), argc); assert(results); for (int i = 1; i < argc; i++) { results[i] = calloc(sizeof(**results), N); assert(results[i]); } for (int j = 0; j < N; j++) { for (int i = 1; i < argc; i++) { struct timespec t0, t1; clock_gettime(CLOCK_MONOTONIC, &t0); size_t nread = 0; int out[2]; if (pipe(out) == -1) { printf("%s: cannot create pipe: %s\n", argv[0], strerror(errno)); exit(1); } pid_t pid = fork(); switch(pid) { case -1: fprintf(stderr, "%s: cannot fork: %s\n", argv[0], strerror(errno)); exit(1); case 0: dup2(out[1], 1); // close(out[0]); // close(out[1]); execl(argv[i], argv[i], (char *)NULL); fprintf(stderr, "%s: cannot exec %s: %s\n", argv[0], argv[i], strerror(errno)); exit(1); default: { close(out[1]); ssize_t n; char buf[16]; while ((n = read(out[0], buf, sizeof(buf))) > 0) { nread += n; } int status; while (waitpid(pid, &status, 0) != pid); } } clock_gettime(CLOCK_MONOTONIC, &t1); results[i][j].time = (t1.tv_sec - t0.tv_sec) * 1E9 + (t1.tv_nsec - t0.tv_nsec); results[i][j].nread = nread; fprintf(stderr, "%s: %s completed in %f ns\n", argv[0], argv[i], results[i][j].time); } } for (int i = 1; i < argc; i++) { resultT m = median(results[i], N); printf("%-20s %8.3f ms %2zd bytes\n", argv[i], m.time / 1E6, m.nread); } return 0; }