From 91a19905b381bf3d17f4c4f81cf72d4eae853a85 Mon Sep 17 00:00:00 2001 From: Kazunobu Kuriyama Date: Mon, 24 Aug 2015 13:44:20 +0900 Subject: test/x11comp: Fix contention between X11 and Xvfb on Mac OS X - Abandon use of -displayfd. - Have x11comp itself look for an unused X11 display number instead. --- test/x11comp.c | 56 +++++++++++++++++++++++++++++++------------------------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/test/x11comp.c b/test/x11comp.c index 71928a6..bf5bbe7 100644 --- a/test/x11comp.c +++ b/test/x11comp.c @@ -39,23 +39,24 @@ main(void) struct xkb_keymap *keymap; xcb_connection_t *conn; int32_t device_id; - int pipefds[2]; int ret, status; - char displayfd[128], display[128]; + char display[512]; char *xkb_path; char *original, *dump; char *envp[] = { NULL }; - char *xvfb_argv[] = { "Xvfb", "-displayfd", displayfd, NULL }; + char *xvfb_argv[] = { "Xvfb", display, NULL }; pid_t xvfb_pid; char *xkbcomp_argv[] = { "xkbcomp", "-I", NULL /* xkb_path */, display, NULL }; pid_t xkbcomp_pid; + char *xhost; + int xdpy_current; + int xdpy_candidate; + /* * What all of this mess does is: - * 1. Launch Xvfb on the next available DISPLAY. Xvfb reports the - * display number to an fd passed with -displayfd once it's - * initialized. We pass a pipe there to read it. + * 1. Launch Xvfb on available DISPLAY. * 2. Make an xcb connection to this display. * 3. Launch xkbcomp to change the keymap of the new display (doing * this programmatically is major work [which we may yet do some @@ -65,30 +66,35 @@ main(void) * 6. Kill the server & clean up. */ - ret = pipe(pipefds); - assert(ret == 0); - - ret = snprintf(displayfd, sizeof(displayfd), "%d", pipefds[1]); - assert(ret >= 0 && ret < sizeof(displayfd)); - - ret = posix_spawnp(&xvfb_pid, "Xvfb", NULL, NULL, xvfb_argv, envp); + ret = xcb_parse_display(NULL, &xhost, &xdpy_current, NULL); + assert(ret != 0); + /* + * IANA assigns TCP port numbers from 6000 through 6063 to X11 + * clients. In addition, the current XCB implementaion shows + * that, when an X11 client tries to establish a TCP connetion, + * the port number needed is specified by adding 6000 to a given + * display number. So, one of reasonable ranges of xdpy_candidate + * is [0, 63]. + */ + for (xdpy_candidate = 63; xdpy_candidate >= 0; xdpy_candidate--) { + char *buf; + + if (xdpy_candidate == xdpy_current) { + continue; + } + snprintf(display, sizeof(display), "%s:%d", xhost, xdpy_candidate); + ret = posix_spawnp(&xvfb_pid, "Xvfb", NULL, NULL, xvfb_argv, envp); + if (ret == 0) { + break; + } + } if (ret != 0) { ret = SKIP_TEST; goto err_ctx; } - close(pipefds[1]); - - display[0] = ':'; - ret = read(pipefds[0], display + 1, sizeof(display) - 1); - if (ret <= 0 || 1 + ret >= sizeof(display) - 1) { - ret = SKIP_TEST; - goto err_xvfd; - } - if (display[ret] == '\n') - display[ret] = '\0'; - display[1 + ret] = '\0'; - close(pipefds[0]); + /* Wait for Xvfb fully waking up to accept a connection from a client. */ + sleep(1); conn = xcb_connect(display, NULL); if (xcb_connection_has_error(conn)) { -- cgit v1.2.1 From 3c12d671cc4f04c70a8b09f9565a223d0e2d52f6 Mon Sep 17 00:00:00 2001 From: Kazunobu Kuriyama Date: Mon, 24 Aug 2015 13:33:32 +0900 Subject: bench: Modify benchmarks for a wider range of platforms - Add the new files bench.c and bench.h to implement a timer module. - Implement the module with clock_gettime(), mach_absolute_time(), or gettimeofday(), depending on a given platform. - Replace the time measurement code of the benchmark programs with the functions of the module. --- Makefile.am | 8 ++- bench/bench.c | 148 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ bench/bench.h | 50 ++++++++++++++++++ bench/compose.c | 23 ++++----- bench/key-proc.c | 23 ++++----- bench/rules.c | 23 ++++----- bench/rulescomp.c | 23 ++++----- configure.ac | 1 + 8 files changed, 249 insertions(+), 50 deletions(-) create mode 100644 bench/bench.c create mode 100644 bench/bench.h diff --git a/Makefile.am b/Makefile.am index eae2b29..1d7ddaf 100644 --- a/Makefile.am +++ b/Makefile.am @@ -250,8 +250,12 @@ check_PROGRAMS += $(TESTS) ## # Benchmarks ## - -BENCH_LDADD = $(TESTS_LDADD) $(RT_LIBS) +check_LTLIBRARIES += libbench.la +libbench_la_SOURCES = \ + bench/bench.c \ + bench/bench.h +BENCH_LDADD = libbench.la +BENCH_LDADD += $(TESTS_LDADD) $(RT_LIBS) check_PROGRAMS += \ bench/key-proc \ diff --git a/bench/bench.c b/bench/bench.c new file mode 100644 index 0000000..9bb535c --- /dev/null +++ b/bench/bench.c @@ -0,0 +1,148 @@ +/* + * Copyright © 2015 Kazunobu Kuriyama + * Ran Benita + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#if defined(HAVE_CLOCK_GETTIME) +#define USE_CLOCK_GETTIME +#include +#elif defined(__MACH__) && __MACH__ == 1 +#define USE_MACH_ABSOLUTE_TIME +#include +#else +/* gettimeofday() - a last resort */ +#include +#endif + +#include +#include +#include + +#include "bench.h" + +static void +set_bench_time(struct bench_time *dest, long seconds, long milliseconds) +{ + dest->seconds = seconds; + dest->milliseconds = milliseconds; +} + +static void +normalize_bench_time(struct bench_time *obj) +{ + if (obj->milliseconds >= 0) { + return; + } + obj->milliseconds += 1000000; + obj->seconds--; +} + +void +bench_timer_reset(struct bench_timer *self) +{ +#if defined(USE_MACH_ABSOLUTE_TIME) + mach_timebase_info_data_t info; + if (mach_timebase_info(&info) == 0) { + self->scaling_factor = info.numer / info.denom; + } +#endif + self->start.seconds = 0L; + self->start.milliseconds = 0L; + self->stop.seconds = 0L; + self->stop.milliseconds = 0L; +} + +void +bench_timer_start(struct bench_timer *self) +{ +#if defined(USE_CLOCK_GETTIME) + struct timespec val; + + (void)clock_gettime(CLOCK_MONOTONIC, &val); + + /* With conversion from nanosecond to millisecond */ + set_bench_time(&self->start, val.tv_sec, val.tv_nsec / 1000); +#elif defined(USE_MACH_ABSOLUTE_TIME) + uint64_t val; + + val = mach_absolute_time(); + + /* With conversion from nanosecond to millisecond */ + set_bench_time(&self->start, + self->scaling_factor * val / 1000000000, + self->scaling_factor * val % 1000000000 / 1000); +#else + struct timeval val; + + (void)gettimeofday(&val, NULL); + + set_bench_time(&self->start, val.tv_sec, val.tv_usec); +#endif +} + +void +bench_timer_stop(struct bench_timer *self) +{ +#if defined(USE_CLOCK_GETTIME) + struct timespec val; + + (void)clock_gettime(CLOCK_MONOTONIC, &val); + + /* With conversion from nanosecond to millisecond */ + set_bench_time(&self->stop, val.tv_sec, val.tv_nsec / 1000); +#elif defined(USE_MACH_ABSOLUTE_TIME) + uint64_t val; + + val = mach_absolute_time(); + + /* With conversion from nanosecond to millisecond */ + set_bench_time(&self->stop, + self->scaling_factor * val / 1000000000, + self->scaling_factor * val % 1000000000 / 1000); +#else + struct timeval val; + + (void)gettimeofday(&val, NULL); + + set_bench_time(&self->stop, val.tv_sec, val.tv_usec); +#endif +} + +void +bench_timer_get_elapsed_time(struct bench_timer *self, struct bench_time *result) +{ + result->seconds = self->stop.seconds - self->start.seconds; + result->milliseconds = self->stop.milliseconds - self->start.milliseconds; +} + +char * +bench_timer_get_elapsed_time_str(struct bench_timer *self) +{ + struct bench_time elapsed; + char *buf; + + bench_timer_get_elapsed_time(self, &elapsed); + normalize_bench_time(&elapsed); + asprintf(&buf, "%ld.%06ld", elapsed.seconds, elapsed.milliseconds); + + return buf; +} diff --git a/bench/bench.h b/bench/bench.h new file mode 100644 index 0000000..5c1769e --- /dev/null +++ b/bench/bench.h @@ -0,0 +1,50 @@ +/* + * Copyright © 2015 Kazunobu Kuriyama + * Ran Benita + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef LIBXKBCOMMON_BENCH_H +#define LIBXKBCOMMON_BENCH_H + +struct bench_time { + long seconds; + long milliseconds; +}; + +struct bench_timer { + struct bench_time start; + struct bench_time stop; +#if defined(__MACH__) && __MACH__ == 1 + uint64_t scaling_factor; +#endif +}; + +void bench_timer_reset(struct bench_timer *self); + +void bench_timer_start(struct bench_timer *self); +void bench_timer_stop(struct bench_timer *self); + +void bench_timer_get_elapsed_time(struct bench_timer *self, struct bench_time *result); +/* It's caller's responsibility to release the returned string using free(). */ +char *bench_timer_get_elapsed_time_str(struct bench_timer *self); + +#endif /* LIBXKBCOMMON_BENCH_H */ diff --git a/bench/compose.c b/bench/compose.c index e2ded57..267b757 100644 --- a/bench/compose.c +++ b/bench/compose.c @@ -26,6 +26,7 @@ #include "xkbcommon/xkbcommon-compose.h" #include "../test/test.h" +#include "bench.h" #define BENCHMARK_ITERATIONS 1000 @@ -33,10 +34,11 @@ int main(void) { struct xkb_context *ctx; - struct timespec start, stop, elapsed; char *path; FILE *file; struct xkb_compose_table *table; + struct bench_timer timer; + char *elapsed; ctx = test_get_context(CONTEXT_NO_FLAG); assert(ctx); @@ -47,7 +49,9 @@ main(void) xkb_context_set_log_level(ctx, XKB_LOG_LEVEL_CRITICAL); xkb_context_set_log_verbosity(ctx, 0); - clock_gettime(CLOCK_MONOTONIC, &start); + bench_timer_reset(&timer); + + bench_timer_start(&timer); for (int i = 0; i < BENCHMARK_ITERATIONS; i++) { rewind(file); table = xkb_compose_table_new_from_file(ctx, file, "", @@ -56,20 +60,15 @@ main(void) assert(table); xkb_compose_table_unref(table); } - clock_gettime(CLOCK_MONOTONIC, &stop); + bench_timer_stop(&timer); fclose(file); free(path); - elapsed.tv_sec = stop.tv_sec - start.tv_sec; - elapsed.tv_nsec = stop.tv_nsec - start.tv_nsec; - if (elapsed.tv_nsec < 0) { - elapsed.tv_nsec += 1000000000; - elapsed.tv_sec--; - } - - fprintf(stderr, "compiled %d compose tables in %ld.%09lds\n", - BENCHMARK_ITERATIONS, elapsed.tv_sec, elapsed.tv_nsec); + elapsed = bench_timer_get_elapsed_time_str(&timer); + fprintf(stderr, "compiled %d compose tables in %ss\n", + BENCHMARK_ITERATIONS, elapsed); + free(elapsed); xkb_context_unref(ctx); return 0; diff --git a/bench/key-proc.c b/bench/key-proc.c index 255f033..56b396a 100644 --- a/bench/key-proc.c +++ b/bench/key-proc.c @@ -25,6 +25,7 @@ #include #include "../test/test.h" +#include "bench.h" #define BENCHMARK_ITERATIONS 20000000 @@ -56,7 +57,8 @@ main(void) struct xkb_context *ctx; struct xkb_keymap *keymap; struct xkb_state *state; - struct timespec start, stop, elapsed; + struct bench_timer timer; + char *elapsed; ctx = test_get_context(0); assert(ctx); @@ -73,19 +75,16 @@ main(void) srand(time(NULL)); - clock_gettime(CLOCK_MONOTONIC, &start); - bench(state); - clock_gettime(CLOCK_MONOTONIC, &stop); + bench_timer_reset(&timer); - elapsed.tv_sec = stop.tv_sec - start.tv_sec; - elapsed.tv_nsec = stop.tv_nsec - start.tv_nsec; - if (elapsed.tv_nsec < 0) { - elapsed.tv_nsec += 1000000000; - elapsed.tv_sec--; - } + bench_timer_start(&timer); + bench(state); + bench_timer_stop(&timer); - fprintf(stderr, "ran %d iterations in %ld.%09lds\n", - BENCHMARK_ITERATIONS, elapsed.tv_sec, elapsed.tv_nsec); + elapsed = bench_timer_get_elapsed_time_str(&timer); + fprintf(stderr, "ran %d iterations in %ss\n", + BENCHMARK_ITERATIONS, elapsed); + free(elapsed); xkb_state_unref(state); xkb_keymap_unref(keymap); diff --git a/bench/rules.c b/bench/rules.c index d92ed07..0dda7e3 100644 --- a/bench/rules.c +++ b/bench/rules.c @@ -26,6 +26,7 @@ #include "../test/test.h" #include "xkbcomp-priv.h" #include "rules.h" +#include "bench.h" #define BENCHMARK_ITERATIONS 20000 @@ -33,12 +34,13 @@ int main(int argc, char *argv[]) { struct xkb_context *ctx; - struct timespec start, stop, elapsed; int i; struct xkb_rule_names rmlvo = { "evdev", "pc105", "us,il", ",", "ctrl:nocaps,grp:menu_toggle", }; struct xkb_component_names kccgst; + struct bench_timer timer; + char *elapsed; ctx = test_get_context(0); assert(ctx); @@ -46,7 +48,9 @@ main(int argc, char *argv[]) xkb_context_set_log_level(ctx, XKB_LOG_LEVEL_CRITICAL); xkb_context_set_log_verbosity(ctx, 0); - clock_gettime(CLOCK_MONOTONIC, &start); + bench_timer_reset(&timer); + + bench_timer_start(&timer); for (i = 0; i < BENCHMARK_ITERATIONS; i++) { assert(xkb_components_from_rules(ctx, &rmlvo, &kccgst)); free(kccgst.keycodes); @@ -54,17 +58,12 @@ main(int argc, char *argv[]) free(kccgst.compat); free(kccgst.symbols); } - clock_gettime(CLOCK_MONOTONIC, &stop); - - elapsed.tv_sec = stop.tv_sec - start.tv_sec; - elapsed.tv_nsec = stop.tv_nsec - start.tv_nsec; - if (elapsed.tv_nsec < 0) { - elapsed.tv_nsec += 1000000000; - elapsed.tv_sec--; - } + bench_timer_stop(&timer); - fprintf(stderr, "processed %d rule files in %ld.%09lds\n", - BENCHMARK_ITERATIONS, elapsed.tv_sec, elapsed.tv_nsec); + elapsed = bench_timer_get_elapsed_time_str(&timer); + fprintf(stderr, "processed %d rule files in %ss\n", + BENCHMARK_ITERATIONS, elapsed); + free(elapsed); xkb_context_unref(ctx); return 0; diff --git a/bench/rulescomp.c b/bench/rulescomp.c index 16f2bf5..650ccf3 100644 --- a/bench/rulescomp.c +++ b/bench/rulescomp.c @@ -24,6 +24,7 @@ #include #include "../test/test.h" +#include "bench.h" #define BENCHMARK_ITERATIONS 2500 @@ -32,7 +33,8 @@ main(int argc, char *argv[]) { struct xkb_context *ctx; struct xkb_keymap *keymap; - struct timespec start, stop, elapsed; + struct bench_timer timer; + char *elapsed; int i; ctx = test_get_context(0); @@ -41,23 +43,20 @@ main(int argc, char *argv[]) xkb_context_set_log_level(ctx, XKB_LOG_LEVEL_CRITICAL); xkb_context_set_log_verbosity(ctx, 0); - clock_gettime(CLOCK_MONOTONIC, &start); + bench_timer_reset(&timer); + + bench_timer_start(&timer); for (i = 0; i < BENCHMARK_ITERATIONS; i++) { keymap = test_compile_rules(ctx, "evdev", "evdev", "us", "", ""); assert(keymap); xkb_keymap_unref(keymap); } - clock_gettime(CLOCK_MONOTONIC, &stop); - - elapsed.tv_sec = stop.tv_sec - start.tv_sec; - elapsed.tv_nsec = stop.tv_nsec - start.tv_nsec; - if (elapsed.tv_nsec < 0) { - elapsed.tv_nsec += 1000000000; - elapsed.tv_sec--; - } + bench_timer_stop(&timer); - fprintf(stderr, "compiled %d keymaps in %ld.%09lds\n", - BENCHMARK_ITERATIONS, elapsed.tv_sec, elapsed.tv_nsec); + elapsed = bench_timer_get_elapsed_time_str(&timer); + fprintf(stderr, "compiled %d keymaps in %ss\n", + BENCHMARK_ITERATIONS, elapsed); + free(elapsed); xkb_context_unref(ctx); return 0; diff --git a/configure.ac b/configure.ac index 57e3fde..671dca0 100644 --- a/configure.ac +++ b/configure.ac @@ -109,6 +109,7 @@ AC_CHECK_LIB(rt, clock_gettime, [AC_SUBST(RT_LIBS, "-lrt")], [AC_SUBST(RT_LIBS, "")], [-lrt]) +AC_CHECK_FUNCS([clock_gettime]) # Define a configuration option for the XKB config root xkb_base=`$PKG_CONFIG --variable=xkb_base xkeyboard-config` -- cgit v1.2.1