X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~mdw/git/mLib/blobdiff_plain/0335afec2c33fefcd6d3cb2c39d014ab2519b2c2..13ee740655965453b2f3fcd7093d2d8b13839903:/test/tvec-main.c diff --git a/test/tvec-main.c b/test/tvec-main.c index fc1a2ae..191449f 100644 --- a/test/tvec-main.c +++ b/test/tvec-main.c @@ -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; }