1 /* Copyright 2016-2021, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
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"
19 #define MAX_DURATION 30
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
};
28 static int n_active_timers
= 0;
29 static int n_fired
= 0;
31 static monotime_t started_at
;
32 static int64_t delay_usec
[N_TIMERS
];
33 static int64_t diffs_mono_usec
[N_TIMERS
];
36 timer_cb(tor_timer_t
*t
, void *arg
, const monotime_t
*now_mono
)
40 tor_gettimeofday(&now
);
41 tor_timer_t
**t_ptr
= arg
;
42 tor_assert(*t_ptr
== t
);
43 int idx
= (int) (t_ptr
- timers
);
45 timersub(&now
, &fire_at
[idx
], &difference
[idx
]);
46 diffs_mono_usec
[idx
] =
47 monotime_diff_usec(&started_at
, now_mono
) -
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());
58 main(int argc
, char **argv
)
62 tor_libevent_cfg_t cfg
;
63 memset(&cfg
, 0, sizeof(cfg
));
64 tor_libevent_initialize(&cfg
);
68 if (crypto_global_init(0, NULL
, NULL
) < 0)
74 tor_gettimeofday(&now
);
75 monotime_get(&started_at
);
76 for (i
= 0; i
< N_TIMERS
; ++i
) {
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
);
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
);
93 timer_disable(timers
[idx
]);
97 tor_libevent_run_event_loop(tor_libevent_get_base(), 0);
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);
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
;
113 const int64_t mean_diff
= total_difference
/ n_active_timers
;
114 printf("mean difference: %"PRId64
" usec\n",
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
);
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)
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");
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");
136 printf("Looks good enough.\n");
142 for (i
= 0; i
< N_TIMERS
; ++i
) {
143 timer_free(timers
[i
]);