123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- /* Copyright 2016-2019, The Tor Project, Inc. */
- /* See LICENSE for licensing information */
- #include "orconfig.h"
- #include <math.h>
- #include <stdio.h>
- #include <string.h>
- #include "lib/evloop/compat_libevent.h"
- #include "lib/evloop/timers.h"
- #include "lib/crypt_ops/crypto_init.h"
- #include "lib/crypt_ops/crypto_rand.h"
- #include "lib/log/util_bug.h"
- #include "lib/time/compat_time.h"
- #include "lib/wallclock/timeval.h"
- #define N_TIMERS 1000
- #define MAX_DURATION 30
- #define N_DISABLE 5
- static struct timeval fire_at[N_TIMERS] = { {0,0} };
- static int is_disabled[N_TIMERS] = {0};
- static int fired[N_TIMERS] = {0};
- static struct timeval difference[N_TIMERS] = { {0,0} };
- static tor_timer_t *timers[N_TIMERS] = {NULL};
- static int n_active_timers = 0;
- static int n_fired = 0;
- static monotime_t started_at;
- static int64_t delay_usec[N_TIMERS];
- static int64_t diffs_mono_usec[N_TIMERS];
- static void
- timer_cb(tor_timer_t *t, void *arg, const monotime_t *now_mono)
- {
- struct timeval now;
- tor_gettimeofday(&now);
- tor_timer_t **t_ptr = arg;
- tor_assert(*t_ptr == t);
- int idx = (int) (t_ptr - timers);
- ++fired[idx];
- timersub(&now, &fire_at[idx], &difference[idx]);
- diffs_mono_usec[idx] =
- monotime_diff_usec(&started_at, now_mono) -
- delay_usec[idx];
- ++n_fired;
- // printf("%d / %d\n",n_fired, N_TIMERS);
- if (n_fired == n_active_timers) {
- tor_libevent_exit_loop_after_callback(tor_libevent_get_base());
- }
- }
- int
- main(int argc, char **argv)
- {
- (void)argc;
- (void)argv;
- tor_libevent_cfg cfg;
- memset(&cfg, 0, sizeof(cfg));
- tor_libevent_initialize(&cfg);
- timers_initialize();
- init_logging(1);
- if (crypto_global_init(0, NULL, NULL) < 0)
- return 1;
- int i;
- int ret;
- struct timeval now;
- tor_gettimeofday(&now);
- monotime_get(&started_at);
- for (i = 0; i < N_TIMERS; ++i) {
- struct timeval delay;
- delay.tv_sec = crypto_rand_int_range(0,MAX_DURATION);
- delay.tv_usec = crypto_rand_int_range(0,1000000);
- delay_usec[i] = delay.tv_sec * 1000000 + delay.tv_usec;
- timeradd(&now, &delay, &fire_at[i]);
- timers[i] = timer_new(timer_cb, &timers[i]);
- timer_schedule(timers[i], &delay);
- ++n_active_timers;
- }
- /* Disable some; we'll make sure they don't trigger. */
- for (i = 0; i < N_DISABLE; ++i) {
- int idx = crypto_rand_int_range(0, N_TIMERS);
- if (is_disabled[idx])
- continue;
- is_disabled[idx] = 1;
- timer_disable(timers[idx]);
- --n_active_timers;
- }
- tor_libevent_run_event_loop(tor_libevent_get_base(), 0);
- int64_t total_difference = 0;
- uint64_t total_square_difference = 0;
- tor_assert(n_fired == n_active_timers);
- for (i = 0; i < N_TIMERS; ++i) {
- if (is_disabled[i]) {
- tor_assert(fired[i] == 0);
- continue;
- }
- tor_assert(fired[i] == 1);
- //int64_t diff = difference[i].tv_usec + difference[i].tv_sec * 1000000;
- int64_t diff = diffs_mono_usec[i];
- total_difference += diff;
- total_square_difference += diff*diff;
- }
- const int64_t mean_diff = total_difference / n_active_timers;
- printf("mean difference: %"PRId64" usec\n",
- (mean_diff));
- const double mean_sq = ((double)total_square_difference)/ n_active_timers;
- const double sq_mean = mean_diff * mean_diff;
- const double stddev = sqrt(mean_sq - sq_mean);
- printf("standard deviation: %lf usec\n", stddev);
- #define MAX_DIFF_USEC (500*1000)
- #define MAX_STDDEV_USEC (500*1000)
- #define ODD_DIFF_USEC (2000)
- #define ODD_STDDEV_USEC (2000)
- if (mean_diff < 0 || mean_diff > MAX_DIFF_USEC || stddev > MAX_STDDEV_USEC) {
- printf("Either your system is under ridiculous load, or the "
- "timer backend is broken.\n");
- ret = 1;
- } else if (mean_diff > ODD_DIFF_USEC || stddev > ODD_STDDEV_USEC) {
- printf("Either your system is a bit slow or the "
- "timer backend is odd.\n");
- ret = 0;
- } else {
- printf("Looks good enough.\n");
- ret = 0;
- }
- timer_free_(NULL);
- for (i = 0; i < N_TIMERS; ++i) {
- timer_free(timers[i]);
- }
- timers_shutdown();
- return ret;
- }
|