test-timers.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. /* Copyright 2016-2019, The Tor Project, Inc. */
  2. /* See LICENSE for licensing information */
  3. #include "orconfig.h"
  4. #include <math.h>
  5. #include <stdio.h>
  6. #include <string.h>
  7. #include "lib/evloop/compat_libevent.h"
  8. #include "lib/evloop/timers.h"
  9. #include "lib/crypt_ops/crypto_init.h"
  10. #include "lib/crypt_ops/crypto_rand.h"
  11. #include "lib/log/util_bug.h"
  12. #include "lib/time/compat_time.h"
  13. #include "lib/wallclock/timeval.h"
  14. #include "lib/subsys/subsys.h"
  15. #include "lib/evloop/evloop_sys.h"
  16. #define N_TIMERS 1000
  17. #define MAX_DURATION 30
  18. #define N_DISABLE 5
  19. static struct timeval fire_at[N_TIMERS] = { {0,0} };
  20. static int is_disabled[N_TIMERS] = {0};
  21. static int fired[N_TIMERS] = {0};
  22. static struct timeval difference[N_TIMERS] = { {0,0} };
  23. static tor_timer_t *timers[N_TIMERS] = {NULL};
  24. static int n_active_timers = 0;
  25. static int n_fired = 0;
  26. static monotime_t started_at;
  27. static int64_t delay_usec[N_TIMERS];
  28. static int64_t diffs_mono_usec[N_TIMERS];
  29. static void
  30. timer_cb(tor_timer_t *t, void *arg, const monotime_t *now_mono)
  31. {
  32. struct timeval now;
  33. tor_gettimeofday(&now);
  34. tor_timer_t **t_ptr = arg;
  35. tor_assert(*t_ptr == t);
  36. int idx = (int) (t_ptr - timers);
  37. ++fired[idx];
  38. timersub(&now, &fire_at[idx], &difference[idx]);
  39. diffs_mono_usec[idx] =
  40. monotime_diff_usec(&started_at, now_mono) -
  41. delay_usec[idx];
  42. ++n_fired;
  43. // printf("%d / %d\n",n_fired, N_TIMERS);
  44. if (n_fired == n_active_timers) {
  45. tor_libevent_exit_loop_after_callback(tor_libevent_get_base());
  46. }
  47. }
  48. int
  49. main(int argc, char **argv)
  50. {
  51. (void)argc;
  52. (void)argv;
  53. if (sys_evloop.initialize()) {
  54. printf("Couldn't initialize evloop subsystem; exiting.\n");
  55. return 1;
  56. }
  57. tor_libevent_cfg cfg;
  58. memset(&cfg, 0, sizeof(cfg));
  59. tor_libevent_initialize(&cfg, 0);
  60. timers_initialize();
  61. init_logging(1);
  62. if (crypto_global_init(0, NULL, NULL) < 0)
  63. return 1;
  64. int i;
  65. int ret;
  66. struct timeval now;
  67. tor_gettimeofday(&now);
  68. monotime_get(&started_at);
  69. for (i = 0; i < N_TIMERS; ++i) {
  70. struct timeval delay;
  71. delay.tv_sec = crypto_rand_int_range(0,MAX_DURATION);
  72. delay.tv_usec = crypto_rand_int_range(0,1000000);
  73. delay_usec[i] = delay.tv_sec * 1000000 + delay.tv_usec;
  74. timeradd(&now, &delay, &fire_at[i]);
  75. timers[i] = timer_new(timer_cb, &timers[i]);
  76. timer_schedule(timers[i], &delay);
  77. ++n_active_timers;
  78. }
  79. /* Disable some; we'll make sure they don't trigger. */
  80. for (i = 0; i < N_DISABLE; ++i) {
  81. int idx = crypto_rand_int_range(0, N_TIMERS);
  82. if (is_disabled[idx])
  83. continue;
  84. is_disabled[idx] = 1;
  85. timer_disable(timers[idx]);
  86. --n_active_timers;
  87. }
  88. tor_libevent_run_event_loop(tor_libevent_get_base(), 0);
  89. int64_t total_difference = 0;
  90. uint64_t total_square_difference = 0;
  91. tor_assert(n_fired == n_active_timers);
  92. for (i = 0; i < N_TIMERS; ++i) {
  93. if (is_disabled[i]) {
  94. tor_assert(fired[i] == 0);
  95. continue;
  96. }
  97. tor_assert(fired[i] == 1);
  98. //int64_t diff = difference[i].tv_usec + difference[i].tv_sec * 1000000;
  99. int64_t diff = diffs_mono_usec[i];
  100. total_difference += diff;
  101. total_square_difference += diff*diff;
  102. }
  103. const int64_t mean_diff = total_difference / n_active_timers;
  104. printf("mean difference: %"PRId64" usec\n",
  105. (mean_diff));
  106. const double mean_sq = ((double)total_square_difference)/ n_active_timers;
  107. const double sq_mean = mean_diff * mean_diff;
  108. const double stddev = sqrt(mean_sq - sq_mean);
  109. printf("standard deviation: %lf usec\n", stddev);
  110. #define MAX_DIFF_USEC (500*1000)
  111. #define MAX_STDDEV_USEC (500*1000)
  112. #define ODD_DIFF_USEC (2000)
  113. #define ODD_STDDEV_USEC (2000)
  114. if (mean_diff < 0 || mean_diff > MAX_DIFF_USEC || stddev > MAX_STDDEV_USEC) {
  115. printf("Either your system is under ridiculous load, or the "
  116. "timer backend is broken.\n");
  117. ret = 1;
  118. } else if (mean_diff > ODD_DIFF_USEC || stddev > ODD_STDDEV_USEC) {
  119. printf("Either your system is a bit slow or the "
  120. "timer backend is odd.\n");
  121. ret = 0;
  122. } else {
  123. printf("Looks good enough.\n");
  124. ret = 0;
  125. }
  126. timer_free_(NULL);
  127. for (i = 0; i < N_TIMERS; ++i) {
  128. timer_free(timers[i]);
  129. }
  130. timers_shutdown();
  131. return ret;
  132. }