tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

test-timers.c (4023B)


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