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
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\
");
}
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);
}
* 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,
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);
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;
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;
}