LCOV - code coverage report
Current view: top level - test - test-timers.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 71 76 93.4 %
Date: 2021-11-24 03:28:48 Functions: 2 2 100.0 %

          Line data    Source code
       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         995 : timer_cb(tor_timer_t *t, void *arg, const monotime_t *now_mono)
      37             : {
      38         995 :   struct timeval now;
      39             : 
      40         995 :   tor_gettimeofday(&now);
      41         995 :   tor_timer_t **t_ptr = arg;
      42         995 :   tor_assert(*t_ptr == t);
      43         995 :   int idx = (int) (t_ptr - timers);
      44         995 :   ++fired[idx];
      45         995 :   timersub(&now, &fire_at[idx], &difference[idx]);
      46        1990 :   diffs_mono_usec[idx] =
      47         995 :     monotime_diff_usec(&started_at, now_mono) -
      48         995 :     delay_usec[idx];
      49         995 :   ++n_fired;
      50             : 
      51             :   // printf("%d / %d\n",n_fired, N_TIMERS);
      52         995 :   if (n_fired == n_active_timers) {
      53           1 :     tor_libevent_exit_loop_after_callback(tor_libevent_get_base());
      54             :   }
      55         995 : }
      56             : 
      57             : int
      58           1 : main(int argc, char **argv)
      59             : {
      60           1 :   (void)argc;
      61           1 :   (void)argv;
      62           1 :   tor_libevent_cfg_t cfg;
      63           1 :   memset(&cfg, 0, sizeof(cfg));
      64           1 :   tor_libevent_initialize(&cfg);
      65           1 :   timers_initialize();
      66           1 :   init_logging(1);
      67             : 
      68           1 :   if (crypto_global_init(0, NULL, NULL) < 0)
      69             :     return 1;
      70             : 
      71           1 :   int i;
      72           1 :   int ret;
      73           1 :   struct timeval now;
      74           1 :   tor_gettimeofday(&now);
      75           1 :   monotime_get(&started_at);
      76        1002 :   for (i = 0; i < N_TIMERS; ++i) {
      77        1000 :     struct timeval delay;
      78        1000 :     delay.tv_sec = crypto_rand_int_range(0,MAX_DURATION);
      79        1000 :     delay.tv_usec = crypto_rand_int_range(0,1000000);
      80        1000 :     delay_usec[i] = delay.tv_sec * 1000000 + delay.tv_usec;
      81        1000 :     timeradd(&now, &delay, &fire_at[i]);
      82        1000 :     timers[i] = timer_new(timer_cb, &timers[i]);
      83        1000 :     timer_schedule(timers[i], &delay);
      84        1000 :     ++n_active_timers;
      85             :   }
      86             : 
      87             :   /* Disable some; we'll make sure they don't trigger. */
      88           6 :   for (i = 0; i < N_DISABLE; ++i) {
      89           5 :     int idx = crypto_rand_int_range(0, N_TIMERS);
      90           5 :     if (is_disabled[idx])
      91           0 :       continue;
      92           5 :     is_disabled[idx] = 1;
      93           5 :     timer_disable(timers[idx]);
      94           5 :     --n_active_timers;
      95             :   }
      96             : 
      97           1 :   tor_libevent_run_event_loop(tor_libevent_get_base(), 0);
      98             : 
      99           1 :   int64_t total_difference = 0;
     100           1 :   uint64_t total_square_difference = 0;
     101           1 :   tor_assert(n_fired == n_active_timers);
     102        1001 :   for (i = 0; i < N_TIMERS; ++i) {
     103        1000 :     if (is_disabled[i]) {
     104           5 :       tor_assert(fired[i] == 0);
     105           5 :       continue;
     106             :     }
     107         995 :     tor_assert(fired[i] == 1);
     108             :     //int64_t diff = difference[i].tv_usec + difference[i].tv_sec * 1000000;
     109         995 :     int64_t diff = diffs_mono_usec[i];
     110         995 :     total_difference += diff;
     111         995 :     total_square_difference += diff*diff;
     112             :   }
     113           1 :   const int64_t mean_diff = total_difference / n_active_timers;
     114           1 :   printf("mean difference: %"PRId64" usec\n",
     115             :          (mean_diff));
     116             : 
     117           1 :   const double mean_sq = ((double)total_square_difference)/ n_active_timers;
     118           1 :   const double sq_mean = mean_diff * mean_diff;
     119           1 :   const double stddev = sqrt(mean_sq - sq_mean);
     120           1 :   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           1 :   if (mean_diff < 0 || mean_diff > MAX_DIFF_USEC || stddev > MAX_STDDEV_USEC) {
     128           0 :     printf("Either your system is under ridiculous load, or the "
     129             :            "timer backend is broken.\n");
     130           0 :     ret = 1;
     131           1 :   } else if (mean_diff > ODD_DIFF_USEC || stddev > ODD_STDDEV_USEC) {
     132           1 :     printf("Either your system is a bit slow or the "
     133             :            "timer backend is odd.\n");
     134           1 :     ret = 0;
     135             :   } else {
     136           0 :     printf("Looks good enough.\n");
     137           0 :     ret = 0;
     138             :   }
     139             : 
     140           1 :   timer_free_(NULL);
     141             : 
     142        1002 :   for (i = 0; i < N_TIMERS; ++i) {
     143        1000 :     timer_free(timers[i]);
     144             :   }
     145           1 :   timers_shutdown();
     146           1 :   return ret;
     147             : }

Generated by: LCOV version 1.14