@@@ bench wip
[mLib] / test / tvec-main.c
index fc1a2ae..191449f 100644 (file)
@@ -61,6 +61,9 @@ static const struct outform {
 const struct tvec_config tvec_adhocconfig =
   { 0, 1, 1, sizeof(struct tvec_reg) };
 
+/* Common benchmark state. */
+static struct bench_state bench;
+
 /* --- @find_outform@ ---
  *
  * Arguments:  @const char *p@ = output name
@@ -105,7 +108,7 @@ static void version(FILE *fp)
 static void usage(FILE *fp)
 {
   pquis(fp, "\
-usage: $ [-f FORMAT] [-o OUTPUT] [-t SECS] [TEST-FILE ...]\n\
+usage: $ [-B CONFIG] [-f FORMAT] [-o OUTPUT] [-t SECS] [TEST-FILE ...]\n\
 ");
 }
 
@@ -114,12 +117,14 @@ static void help(FILE *fp)
   version(fp); fputc('\n', fp);
   usage(fp); fputs("\
 Options:\n\
-  -h, --help           show this help text.\n\
-  -v, --version                show version number.\n\
-  -u, --usage          show usage synopsis.\n\
+  -h, --help                   show this help text.\n\
+  -v, --version                        show version number.\n\
+  -u, --usage                  show usage synopsis.\n\
 \n\
-  -f, --format=FORMAT  produce output in FORMAT.\n\
-  -o, --output=OUTPUT  write output to OUTPUT file.\n\
+  -B, --bench-config=CONFIG    set benchmark configuration string.\n\
+  -f, --format=FORMAT          produce output in FORMAT.\n\
+  -o, --output=OUTPUT          write output to OUTPUT file.\n\
+  -t, --target-time=DURATION   run benchmarks for DURATION.\n\
 ", fp);
 }
 
@@ -136,6 +141,8 @@ Options:\n\
  * Use:                Parse arguments and set up the test vector state @*tv_out@.
  *             If errors occur, print messages to standard error and exit
  *             with status 2.
+ *
+ *             This function also establishes a common benchmark state.
  */
 
 void tvec_parseargs(int argc, char *argv[], struct tvec_state *tv_out,
@@ -144,30 +151,37 @@ void tvec_parseargs(int argc, char *argv[], struct tvec_state *tv_out,
   FILE *ofp = 0;
   const struct outform *of = 0;
   struct tvec_output *o;
-  const char *p;
+  const char *benchconf = 0;
+  double benchtime = 1.0, scale;
+  struct bench_timer *tm;
+  const char *p; char *q;
   int opt;
   unsigned f = 0;
 #define f_bogus 1u
+#define f_bench 2u
 
   static const struct option options[] = {
     { "help",          0,              0,      'h' },
     { "version",       0,              0,      'v' },
     { "usage",         0,              0,      'u' },
 
+    { "bench-config",  OPTF_ARGREQ,    0,      'B' },
     { "format",                OPTF_ARGREQ,    0,      'f' },
     { "output",                OPTF_ARGREQ,    0,      'o' },
+    { "target-time",   OPTF_ARGREQ,    0,      't' },
     { 0,               0,              0,      0 }
   };
 
   ego(argv[0]);
   for (;;) {
-    opt = mdwopt(argc, argv, "hvu" "f:o:", options, 0, 0, 0);
+    opt = mdwopt(argc, argv, "hvu" "B:f:o:t:", options, 0, 0, 0);
     if (opt < 0) break;
     switch (opt) {
       case 'h': help(stdout); exit(0);
       case 'v': version(stdout); exit(0);
       case 'u': usage(stdout); exit(0);
 
+      case 'B': benchconf = optarg; f |= f_bench; break;
       case 'f': of = find_outform(optarg); break;
       case 'o':
        if (ofp) fclose(ofp);
@@ -176,6 +190,21 @@ void tvec_parseargs(int argc, char *argv[], struct tvec_state *tv_out,
          die(2, "failed to open `%s' for writing: %s",
              optarg, strerror(errno));
        break;
+      case 't':
+       if (*optarg != '.' && !ISDIGIT(*optarg)) goto bad_time;
+       errno = 0; benchtime = strtod(optarg, &q);
+       if (errno) goto bad_time;
+       p = q;
+       if (ISSPACE(*p)) {
+         do p++; while (ISSPACE(*p));
+         if (!*p) goto bad_time;
+       }
+       if (tvec_parsedurunit(&scale, &p)) goto bad_time;
+       if (*p) goto bad_time;
+       benchtime *= scale; f |= f_bench;
+       break;
+      bad_time:
+       die(2, "invalid time duration `%s'", optarg);
 
       default:
        f |= f_bogus;
@@ -191,6 +220,17 @@ void tvec_parseargs(int argc, char *argv[], struct tvec_state *tv_out,
   if (of) o = of->makefn(ofp);
   else o = tvec_dfltout(ofp);
 
+  tm = bench_createtimer(benchconf);
+  if (tm) {
+    bench_init(&bench, tm); bench.target_s = benchtime;
+    tvec_benchstate = &bench;
+  } else if (f&f_bench) {
+    moan("failed to create benchmark timer");
+    if (!getenv("MLIB_BENCH_DEBUG"))
+      moan("set `MLIB_BENCH_DEBUG=t' in the envionment for more detail");
+    exit(2);
+  }
+
   tvec_begin(tv_out, config, o); *argpos_out = optind;
 }