New version.
[runlisp] / bench / timeit.c
1 #include <errno.h>
2 #include <stdarg.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <time.h>
7
8 #include <unistd.h>
9 #include <sys/resource.h>
10 #include <sys/time.h>
11 #include <sys/wait.h>
12
13 static const char *progname = "timeit";
14
15 static void set_progname(const char *prog)
16 {
17 const char *p;
18
19 p = strrchr(prog, '/');
20 progname = p ? p + 1 : progname;
21 }
22
23 static void lose(const char *msg, ...)
24 {
25 va_list ap;
26
27 va_start(ap, msg);
28 fprintf(stderr, "%s: ", progname);
29 vfprintf(stderr, msg, ap);
30 fputc('\n', stderr);
31 va_end(ap);
32 exit(127);
33 }
34
35 static double timeval_to_float(const struct timeval *tv)
36 { return (tv->tv_sec + tv->tv_usec*1e-6); }
37
38 int main(int argc, char *argv[])
39 {
40 struct rusage ru;
41 struct timeval t0, t1, t;
42 pid_t kid;
43 int i, st;
44
45 set_progname(argv[0]);
46 gettimeofday(&t0, 0);
47 kid = fork(); if (kid < 0) lose("fork failed: %s", strerror(errno));
48 if (!kid) {
49 execvp(argv[1], argv + 1);
50 lose("exec (`%s') failed: %s", argv[1], strerror(errno));
51 }
52 if (wait4(kid, &st, 0, &ru) < 0) lose("wait failed: %s", strerror(errno));
53 gettimeofday(&t1, 0);
54 if (st) {
55 if (WIFSIGNALED(st))
56 lose("program killed by signal %d\n", WTERMSIG(st));
57 else if (WIFEXITED(st))
58 lose("program failed with status %d\n", WEXITSTATUS(st));
59 else
60 lose("program exited with incomprehensible status 0x%04x\n", st);
61 }
62
63 if (t0.tv_usec > t1.tv_usec) {
64 t.tv_sec = t1.tv_sec - t0.tv_sec - 1;
65 t.tv_usec = t1.tv_usec + 1000000 - t0.tv_usec;
66 } else {
67 t.tv_sec = t1.tv_sec - t0.tv_sec;
68 t.tv_usec = t1.tv_usec - t0.tv_usec;
69 }
70
71 for (i = 1; i < argc; i++) {
72 if (i > 1) fputc(' ', stderr);
73 fputs(argv[i], stderr);
74 }
75 fprintf(stderr, ": elapsed = %.4fs; user = %.4fs; system = %.4fs\n",
76 timeval_to_float(&t),
77 timeval_to_float(&ru.ru_utime),
78 timeval_to_float(&ru.ru_stime));
79 return (0);
80 }