test-timers.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. /* Copyright 2016, 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. #ifdef HAVE_EVENT2_EVENT_H
  8. #include <event2/event.h>
  9. #else
  10. #include <event.h>
  11. #endif
  12. #include "compat.h"
  13. #include "compat_libevent.h"
  14. #include "crypto.h"
  15. #include "timers.h"
  16. #include "util.h"
  17. #define N_TIMERS 1000
  18. #define MAX_DURATION 30
  19. #define N_DISABLE 5
  20. static struct timeval fire_at[N_TIMERS] = {{0,0}};
  21. static int is_disabled[N_TIMERS] = {0};
  22. static int fired[N_TIMERS] = {0};
  23. static struct timeval difference[N_TIMERS] = {{0,0}};
  24. static tor_timer_t *timers[N_TIMERS] = {NULL};
  25. static int n_active_timers = 0;
  26. static int n_fired = 0;
  27. static void
  28. timer_cb(tor_timer_t *t, void *arg, const struct timeval *now)
  29. {
  30. tor_timer_t **t_ptr = arg;
  31. tor_assert(*t_ptr == t);
  32. int idx = (int) (t_ptr - timers);
  33. ++fired[idx];
  34. timersub(now, &fire_at[idx], &difference[idx]);
  35. ++n_fired;
  36. // printf("%d / %d\n",n_fired, N_TIMERS);
  37. if (n_fired == n_active_timers) {
  38. event_base_loopbreak(tor_libevent_get_base());
  39. }
  40. }
  41. int
  42. main(int argc, char **argv)
  43. {
  44. (void)argc;
  45. (void)argv;
  46. tor_libevent_cfg cfg;
  47. memset(&cfg, 0, sizeof(cfg));
  48. tor_libevent_initialize(&cfg);
  49. timers_initialize();
  50. int i;
  51. int ret;
  52. struct timeval now;
  53. tor_gettimeofday(&now);
  54. for (i = 0; i < N_TIMERS; ++i) {
  55. struct timeval delay;
  56. delay.tv_sec = crypto_rand_int_range(0,MAX_DURATION);
  57. delay.tv_usec = crypto_rand_int_range(0,1000000);
  58. timeradd(&now, &delay, &fire_at[i]);
  59. timers[i] = timer_new(timer_cb, &timers[i]);
  60. timer_schedule(timers[i], &delay);
  61. ++n_active_timers;
  62. }
  63. /* Disable some; we'll make sure they don't trigger. */
  64. for (i = 0; i < N_DISABLE; ++i) {
  65. int idx = crypto_rand_int_range(0, N_TIMERS);
  66. if (is_disabled[idx])
  67. continue;
  68. is_disabled[idx] = 1;
  69. timer_disable(timers[idx]);
  70. --n_active_timers;
  71. }
  72. event_base_loop(tor_libevent_get_base(), 0);
  73. uint64_t total_difference = 0;
  74. uint64_t total_square_difference = 0;
  75. tor_assert(n_fired == n_active_timers);
  76. for (i = 0; i < N_TIMERS; ++i) {
  77. if (is_disabled[i]) {
  78. tor_assert(fired[i] == 0);
  79. continue;
  80. }
  81. tor_assert(fired[i] == 1);
  82. uint64_t diff = difference[i].tv_usec + difference[i].tv_sec * 1000000;
  83. total_difference += diff;
  84. total_square_difference += diff*diff;
  85. }
  86. const uint64_t mean_diff = total_difference / n_active_timers;
  87. printf("mean difference: "U64_FORMAT" usec\n",
  88. U64_PRINTF_ARG(mean_diff));
  89. const double mean_sq = ((double)total_square_difference)/ n_active_timers;
  90. const double sq_mean = mean_diff * mean_diff;
  91. const double stddev = sqrt(mean_sq - sq_mean);
  92. printf("standard deviation: %lf usec\n", stddev);
  93. if (mean_diff > 500*1000 || stddev > 500*1000) {
  94. printf("Either your system is under ridiculous load, or the "
  95. "timer backend is broken.\n");
  96. ret = 1;
  97. } else if (mean_diff > 2000 || stddev > 2000) {
  98. printf("Either your system is a bit slow or the "
  99. "timer backend is odd.\n");
  100. ret = 0;
  101. } else {
  102. printf("Looks good enough.\n");
  103. ret = 0;
  104. }
  105. timer_free(NULL);
  106. for (i = 0; i < N_TIMERS; ++i) {
  107. timer_free(timers[i]);
  108. }
  109. timers_shutdown();
  110. return ret;
  111. }