key-proc.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. /*
  2. * Copyright © 2012 Ran Benita <ran234@gmail.com>
  3. * SPDX-License-Identifier: MIT
  4. */
  5. #include "config.h"
  6. #include <stdlib.h>
  7. #include <time.h>
  8. #include "xkbcommon/xkbcommon.h"
  9. #include "test/test.h"
  10. #include "tools/tools-common.h"
  11. #include "bench.h"
  12. #include "utils.h"
  13. #include "utils-random.h"
  14. #define BENCHMARK_ITERATIONS 3000000
  15. NOINLINE static void
  16. bench_legacy_api(struct xkb_state *state)
  17. {
  18. bool keys[256] = { 0 };
  19. volatile unsigned long acc_changed = 0;
  20. volatile unsigned long acc_keysym = 0;
  21. for (size_t i = 0; i < BENCHMARK_ITERATIONS; i++) {
  22. const xkb_keycode_t keycode = (random() % (255 - 9)) + 9;
  23. const enum xkb_key_direction direction = (keys[keycode])
  24. ? XKB_KEY_UP : XKB_KEY_DOWN;
  25. const enum xkb_state_component changed =
  26. xkb_state_update_key(state, keycode, direction);
  27. acc_changed += (unsigned long)changed;
  28. if (keys[keycode]) {
  29. const xkb_keysym_t keysym =
  30. xkb_state_key_get_one_sym(state, keycode);
  31. acc_keysym += (unsigned long)keysym;
  32. }
  33. keys[keycode] = !keys[keycode];
  34. }
  35. }
  36. NOINLINE static void
  37. bench_modern_api(struct xkb_machine *sm,
  38. struct xkb_events *events,
  39. struct xkb_state *state)
  40. {
  41. bool keys[256] = { 0 };
  42. volatile unsigned long acc_ret = 0;
  43. volatile unsigned long acc_changed = 0;
  44. volatile unsigned long acc_keysym = 0;
  45. const struct xkb_event *event;
  46. for (size_t i = 0; i < BENCHMARK_ITERATIONS; i++) {
  47. const xkb_keycode_t keycode = (random() % (255 - 9)) + 9;
  48. const enum xkb_key_direction direction = (keys[keycode])
  49. ? XKB_KEY_UP : XKB_KEY_DOWN;
  50. const int ret = xkb_machine_process_key(sm, keycode, direction, events);
  51. acc_ret += (unsigned long)ret;
  52. enum xkb_state_component changed = 0;
  53. while ((event = xkb_events_next(events))) {
  54. changed |= xkb_state_update_event(state, event);
  55. }
  56. acc_changed += (unsigned long)changed;
  57. if (keys[keycode]) {
  58. const xkb_keysym_t keysym =
  59. xkb_state_key_get_one_sym(state, keycode);
  60. acc_keysym += (unsigned long)keysym;
  61. }
  62. keys[keycode] = !keys[keycode];
  63. }
  64. }
  65. int
  66. main(void)
  67. {
  68. struct xkb_context *ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
  69. assert(ctx);
  70. const enum xkb_keymap_format format = XKB_KEYMAP_FORMAT_TEXT_V1;
  71. const enum xkb_keymap_compile_flags flags = XKB_KEYMAP_COMPILE_NO_FLAGS;
  72. struct xkb_keymap *keymap;
  73. if (is_pipe_or_regular_file(STDIN_FILENO)) {
  74. fprintf(stderr, "Bench using keymap from stdin\n");
  75. FILE *file = tools_read_stdin();
  76. assert(file);
  77. keymap = xkb_keymap_new_from_file(ctx, file, format, flags);
  78. assert(keymap);
  79. } else {
  80. fprintf(stderr, "Bench using keymap from fixed RMLVO\n");
  81. static const struct xkb_rule_names rmlvo = {
  82. .rules = "evdev",
  83. .model = "pc104",
  84. .layout = "us,ru,il,de",
  85. .variant = ",,,neo",
  86. .options = "grp:menu_toggle"
  87. };
  88. keymap = xkb_keymap_new_from_names2(ctx, &rmlvo, format, flags);
  89. assert(keymap);
  90. }
  91. xkb_enable_quiet_logging(ctx);
  92. srandom((unsigned) time(NULL));
  93. struct bench bench;
  94. struct bench_time elapsed;
  95. long average;
  96. char *elapsed_str;
  97. /*
  98. * Legacy server state machine API
  99. */
  100. struct xkb_state *state = xkb_state_new(keymap);
  101. assert(state);
  102. bench_start2(&bench);
  103. bench_legacy_api(state);
  104. bench_stop2(&bench);
  105. xkb_state_unref(state);
  106. bench_elapsed(&bench, &elapsed);
  107. average = (bench_time_elapsed_nanoseconds(&elapsed)) / BENCHMARK_ITERATIONS;
  108. elapsed_str = bench_elapsed_str(&bench);
  109. fprintf(stdout, "Legacy server API: average=%ldns; %d iterations in %ss\n",
  110. average, BENCHMARK_ITERATIONS, elapsed_str);
  111. free(elapsed_str);
  112. /*
  113. * Full server state machine API
  114. */
  115. struct xkb_machine_builder *builder =
  116. xkb_machine_builder_new(keymap, XKB_MACHINE_BUILDER_NO_FLAGS);
  117. assert(builder);
  118. struct xkb_machine *sm = xkb_machine_new(builder);
  119. assert(sm);
  120. xkb_machine_builder_destroy(builder);
  121. struct xkb_events *events = xkb_events_new_batch(ctx, XKB_EVENTS_NO_FLAGS);
  122. assert(events);
  123. state = xkb_state_new(keymap);
  124. assert(state);
  125. bench_start2(&bench);
  126. bench_modern_api(sm, events, state);
  127. bench_stop2(&bench);
  128. xkb_state_unref(state);
  129. xkb_events_destroy(events);
  130. xkb_machine_unref(sm);
  131. bench_elapsed(&bench, &elapsed);
  132. average = (bench_time_elapsed_nanoseconds(&elapsed)) / BENCHMARK_ITERATIONS;
  133. elapsed_str = bench_elapsed_str(&bench);
  134. fprintf(stdout, "Modern server API: average=%ldns, %d iterations in %ss\n",
  135. average, BENCHMARK_ITERATIONS, elapsed_str);
  136. free(elapsed_str);
  137. xkb_keymap_unref(keymap);
  138. xkb_context_unref(ctx);
  139. return EXIT_SUCCESS;
  140. }