hello/timethem.c

94 lines
2.6 KiB
C

#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#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;
}