chiark / gitweb /
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 }