| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235 |
- /*
- * Copyright © 2012 Ran Benita <ran234@gmail.com>
- * SPDX-License-Identifier: MIT
- */
- #include "config.h"
- #include <getopt.h>
- #include <stdlib.h>
- #include "xkbcommon/xkbcommon.h"
- #include "../test/test.h"
- #include "xkbcomp/rules.h"
- #include "bench.h"
- static const unsigned int DEFAULT_ITERATIONS = 20000;
- static const double DEFAULT_STDEV = 0.05;
- static void
- usage(char **argv)
- {
- printf("Usage: %s [OPTIONS]\n"
- "\n"
- "Benchmark compilation of the given RMLVO\n"
- "\n"
- "Options:\n"
- " --help\n"
- " Print this help and exit\n"
- " --iter\n"
- " Exact number of iterations to run\n"
- " --stdev\n"
- " Minimal relative standard deviation (percentage) to reach.\n"
- " (default: %f)\n"
- "Note: --iter and --stdev are mutually exclusive.\n"
- "\n"
- "XKB-specific options:\n"
- " --rules <rules>\n"
- " The XKB ruleset (default: '%s')\n"
- " --model <model>\n"
- " The XKB model (default: '%s')\n"
- " --layout <layout>\n"
- " The XKB layout (default: '%s')\n"
- " --variant <variant>\n"
- " The XKB layout variant (default: '%s')\n"
- " --options <options>\n"
- " The XKB options (default: '%s')\n"
- "\n",
- argv[0], DEFAULT_STDEV * 100, DEFAULT_XKB_RULES,
- DEFAULT_XKB_MODEL, DEFAULT_XKB_LAYOUT,
- DEFAULT_XKB_VARIANT ? DEFAULT_XKB_VARIANT : "<none>",
- DEFAULT_XKB_OPTIONS ? DEFAULT_XKB_OPTIONS : "<none>");
- }
- int
- main(int argc, char *argv[])
- {
- struct bench bench;
- struct bench_time elapsed;
- struct estimate est;
- bool explicit_iterations = false;
- struct xkb_rule_names rmlvo = {
- .rules = DEFAULT_XKB_RULES,
- .model = DEFAULT_XKB_MODEL,
- /* layout and variant are tied together, so we either get user-supplied for
- * both or default for both, see below */
- .layout = NULL,
- .variant = NULL,
- .options = DEFAULT_XKB_OPTIONS,
- };
- unsigned int max_iterations = DEFAULT_ITERATIONS;
- double stdev = DEFAULT_STDEV;
- enum options {
- OPT_RULES,
- OPT_MODEL,
- OPT_LAYOUT,
- OPT_VARIANT,
- OPT_OPTION,
- OPT_ITERATIONS,
- OPT_STDEV,
- };
- static struct option opts[] = {
- {"help", no_argument, 0, 'h'},
- {"rules", required_argument, 0, OPT_RULES},
- {"model", required_argument, 0, OPT_MODEL},
- {"layout", required_argument, 0, OPT_LAYOUT},
- {"variant", required_argument, 0, OPT_VARIANT},
- {"options", required_argument, 0, OPT_OPTION},
- {"iter", required_argument, 0, OPT_ITERATIONS},
- {"stdev", required_argument, 0, OPT_STDEV},
- {0, 0, 0, 0},
- };
- while (1) {
- int c;
- int option_index = 0;
- c = getopt_long(argc, argv, "h", opts, &option_index);
- if (c == -1)
- break;
- switch (c) {
- case 'h':
- usage(argv);
- exit(EXIT_SUCCESS);
- case OPT_RULES:
- rmlvo.rules = optarg;
- break;
- case OPT_MODEL:
- rmlvo.model = optarg;
- break;
- case OPT_LAYOUT:
- rmlvo.layout = optarg;
- break;
- case OPT_VARIANT:
- rmlvo.variant = optarg;
- break;
- case OPT_OPTION:
- rmlvo.options = optarg;
- break;
- case OPT_ITERATIONS:
- if (max_iterations == 0) {
- usage(argv);
- exit(EXIT_INVALID_USAGE);
- }
- {
- errno = 0;
- char *endp = optarg;
- const unsigned long raw = strtoul(optarg, &endp, 10);
- if (errno || optarg == endp || *endp != '\0' ||
- !raw || raw > UINT_MAX) {
- fprintf(stderr,
- "ERROR: invalid 'iter' parameter; "
- "using default: %u\n", DEFAULT_ITERATIONS);
- max_iterations = DEFAULT_ITERATIONS;
- } else {
- max_iterations = (unsigned int)raw;
- }
- }
- explicit_iterations = true;
- break;
- case OPT_STDEV:
- if (explicit_iterations) {
- usage(argv);
- exit(EXIT_INVALID_USAGE);
- }
- {
- errno = 0;
- char *endp = optarg;
- stdev = strtod(optarg, &endp) / 100;
- if (errno || optarg == endp || *endp != '\0' || stdev <= 0) {
- fprintf(stderr,
- "ERROR: invalid 'stdev' parameter; "
- "using default: %.3f\n", DEFAULT_STDEV);
- stdev = DEFAULT_STDEV;
- }
- }
- max_iterations = 0;
- break;
- default:
- usage(argv);
- exit(EXIT_INVALID_USAGE);
- }
- }
- /* Now fill in the layout */
- if (!rmlvo.layout || !*rmlvo.layout) {
- if (rmlvo.variant && *rmlvo.variant) {
- fprintf(stderr, "Error: a variant requires a layout\n");
- return EXIT_INVALID_USAGE;
- }
- rmlvo.layout = DEFAULT_XKB_LAYOUT;
- rmlvo.variant = DEFAULT_XKB_VARIANT;
- }
- struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
- if (!context)
- exit(EXIT_FAILURE);
- xkb_enable_quiet_logging(context);
- if (explicit_iterations) {
- stdev = 0;
- bench_start2(&bench);
- for (unsigned int i = 0; i < max_iterations; i++) {
- struct xkb_component_names kccgst;
- assert(xkb_components_from_rules_names(context, &rmlvo, &kccgst, NULL));
- free(kccgst.keycodes);
- free(kccgst.types);
- free(kccgst.compatibility);
- free(kccgst.symbols);
- free(kccgst.geometry);
- }
- bench_stop2(&bench);
- bench_elapsed(&bench, &elapsed);
- est.elapsed = (bench_time_elapsed_nanoseconds(&elapsed)) / max_iterations;
- est.stdev = 0;
- } else {
- bench_start2(&bench);
- BENCH(stdev, max_iterations, elapsed, est,
- struct xkb_component_names kccgst;
- assert(xkb_components_from_rules_names(context, &rmlvo, &kccgst, NULL));
- free(kccgst.keycodes);
- free(kccgst.types);
- free(kccgst.compatibility);
- free(kccgst.symbols);
- free(kccgst.geometry);
- );
- bench_stop2(&bench);
- }
- struct bench_time total_elapsed;
- bench_elapsed(&bench, &total_elapsed);
- if (explicit_iterations) {
- fprintf(stderr,
- "mean: %lld µs; compiled %u rules in %ld.%06lds\n",
- est.elapsed / 1000, max_iterations,
- total_elapsed.seconds, total_elapsed.nanoseconds / 1000);
- } else {
- fprintf(stderr,
- "mean: %lld µs; stdev: %Lf%% (target: %f%%); "
- "last run: compiled %u rules in %ld.%06lds; "
- "total time: %ld.%06lds\n", est.elapsed / 1000,
- (long double) est.stdev * 100.0 / (long double) est.elapsed,
- stdev * 100,
- max_iterations, elapsed.seconds, elapsed.nanoseconds / 1000,
- total_elapsed.seconds, total_elapsed.nanoseconds / 1000);
- }
- xkb_context_unref(context);
- return EXIT_SUCCESS;
- }
|