mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-11 05:33:47 +01:00
Add a function to compute millisecond time difference quickly.
Our main function, though accurate on all platforms, can be very slow on 32-bit hosts. This one is faster on all 32-bit hosts, and accurate everywhere except apple, where it will typically be off by 1%. But since 32-bit apple is a relic anyway, I think we should be fine.
This commit is contained in:
parent
7cbc44eeb1
commit
9abf541f7f
@ -279,6 +279,7 @@ monotime_reset_ratchets_for_testing(void)
|
||||
* nanoseconds.
|
||||
*/
|
||||
static struct mach_timebase_info mach_time_info;
|
||||
static struct mach_timebase_info mach_time_info_msec_cvt;
|
||||
static int monotime_shift = 0;
|
||||
|
||||
static void
|
||||
@ -296,6 +297,14 @@ monotime_init_internal(void)
|
||||
// requires that tor_log2(0) == 0.
|
||||
monotime_shift = tor_log2(ms_per_tick);
|
||||
}
|
||||
{
|
||||
// For converting ticks to milliseconds in a 32-bit-friendly way, we
|
||||
// will first right-shift by 20, and then multiply by 20/19, since
|
||||
// (1<<20) * 19/20 is about 1e6. We precompute a new numerate and
|
||||
// denominator here to avoid multiple multiplies.
|
||||
mach_time_info_msec_cvt.numer = mach_time_info.numer * 20;
|
||||
mach_time_info_msec_cvt.denom = mach_time_info.denom * 19;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -345,6 +354,22 @@ monotime_diff_nsec(const monotime_t *start,
|
||||
return diff_nsec;
|
||||
}
|
||||
|
||||
int32_t
|
||||
monotime_coarse_diff_msec32_(const monotime_coarse_t *start,
|
||||
const monotime_coarse_t *end)
|
||||
{
|
||||
if (BUG(mach_time_info.denom == 0)) {
|
||||
monotime_init();
|
||||
}
|
||||
const int64_t diff_ticks = end->abstime_ - start->abstime_;
|
||||
|
||||
/* We already require in di_ops.c that right-shift performs a sign-extend. */
|
||||
const int32_t diff_microticks = (int32_t)(diff_ticks >> 20);
|
||||
|
||||
return (diff_microticks * mach_time_info_msec_cvt.numer) /
|
||||
mach_time_info_msec_cvt.denom;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
monotime_coarse_to_stamp(const monotime_coarse_t *t)
|
||||
{
|
||||
@ -443,6 +468,15 @@ monotime_diff_nsec(const monotime_t *start,
|
||||
return diff_nsec;
|
||||
}
|
||||
|
||||
int32_t
|
||||
monotime_coarse_diff_msec32_(const monotime_coarse_t *start,
|
||||
const monotime_coarse_t *end)
|
||||
{
|
||||
const int32_t diff_sec = (int32_t)(end->ts_.tv_sec - start->ts_.tv_sec);
|
||||
const int32_t diff_nsec = (int32_t)(end->ts_.tv_nsec - start->ts_.tv_nsec);
|
||||
return diff_sec * 1000 + diff_nsec / ONE_MILLION;
|
||||
}
|
||||
|
||||
/* This value is ONE_BILLION >> 20. */
|
||||
static const uint32_t STAMP_TICKS_PER_SECOND = 953;
|
||||
|
||||
@ -592,6 +626,13 @@ monotime_coarse_diff_msec(const monotime_coarse_t *start,
|
||||
return diff_ticks;
|
||||
}
|
||||
|
||||
int32_t
|
||||
monotime_coarse_diff_msec32_(const monotime_coarse_t *start,
|
||||
const monotime_coarse_t *end)
|
||||
{
|
||||
return (int32_t)monotime_coarse_diff_msec(start, end)
|
||||
}
|
||||
|
||||
int64_t
|
||||
monotime_coarse_diff_usec(const monotime_coarse_t *start,
|
||||
const monotime_coarse_t *end)
|
||||
@ -677,6 +718,15 @@ monotime_diff_nsec(const monotime_t *start,
|
||||
return (diff.tv_sec * ONE_BILLION + diff.tv_usec * 1000);
|
||||
}
|
||||
|
||||
int32_t
|
||||
monotime_coarse_diff_msec32_(const monotime_coarse_t *start,
|
||||
const monotime_coarse_t *end)
|
||||
{
|
||||
struct timeval diff;
|
||||
timersub(&end->tv_, &start->tv_, &diff);
|
||||
return diff.tv_sec * 1000 + diff.tv_usec / 1000;
|
||||
}
|
||||
|
||||
/* This value is ONE_MILLION >> 10. */
|
||||
static const uint32_t STAMP_TICKS_PER_SECOND = 976;
|
||||
|
||||
|
@ -173,6 +173,33 @@ void monotime_coarse_add_msec(monotime_coarse_t *out,
|
||||
#define monotime_coarse_add_msec monotime_add_msec
|
||||
#endif /* defined(MONOTIME_COARSE_TYPE_IS_DIFFERENT) */
|
||||
|
||||
/**
|
||||
* As monotime_coarse_diff_msec, but avoid 64-bit division.
|
||||
*
|
||||
* Requires that the difference fit into an int32_t; not for use with
|
||||
* large time differences.
|
||||
*/
|
||||
int32_t monotime_coarse_diff_msec32_(const monotime_coarse_t *start,
|
||||
const monotime_coarse_t *end);
|
||||
|
||||
/**
|
||||
* As monotime_coarse_diff_msec, but avoid 64-bit division if it is expensive.
|
||||
*
|
||||
* Requires that the difference fit into an int32_t; not for use with
|
||||
* large time differences.
|
||||
*/
|
||||
static inline int32_t
|
||||
monotime_coarse_diff_msec32(const monotime_coarse_t *start,
|
||||
const monotime_coarse_t *end)
|
||||
{
|
||||
#if SIZEOF_VOID_P == 8
|
||||
// on a 64-bit platform, let's assume 64/64 division is cheap.
|
||||
return (int32_t) monotime_coarse_diff_msec(start, end);
|
||||
#else
|
||||
return monotime_coarse_diff_msec32_(start, end);
|
||||
#endif
|
||||
}
|
||||
|
||||
MOCK_DECL(void, tor_gettimeofday, (struct timeval *timeval));
|
||||
|
||||
#ifdef TOR_UNIT_TESTS
|
||||
|
@ -626,11 +626,8 @@ cell_ewma_get_current_tick_and_fraction(double *remainder_out)
|
||||
}
|
||||
monotime_coarse_t now;
|
||||
monotime_coarse_get(&now);
|
||||
// XXXX this does a division operation that can be slow on 32-bit
|
||||
// XXXX systems.
|
||||
int32_t msec_diff =
|
||||
(int32_t)monotime_coarse_diff_msec(&start_of_current_tick,
|
||||
&now);
|
||||
int32_t msec_diff = monotime_coarse_diff_msec32(&start_of_current_tick,
|
||||
&now);
|
||||
if (msec_diff > (1000*EWMA_TICK_LEN)) {
|
||||
unsigned ticks_difference = msec_diff / (1000*EWMA_TICK_LEN);
|
||||
monotime_coarse_add_msec(&start_of_current_tick,
|
||||
|
@ -6035,6 +6035,9 @@ test_util_monotonic_time_add_msec(void *arg)
|
||||
monotime_coarse_add_msec(&ct2, &ct1, 1337);
|
||||
tt_i64_op(monotime_diff_msec(&t1, &t2), OP_EQ, 1337);
|
||||
tt_i64_op(monotime_coarse_diff_msec(&ct1, &ct2), OP_EQ, 1337);
|
||||
// The 32-bit variant must be within 1% of the regular one.
|
||||
tt_int_op(monotime_coarse_diff_msec32_(&ct1, &ct2), OP_GT, 1323);
|
||||
tt_int_op(monotime_coarse_diff_msec32_(&ct1, &ct2), OP_LT, 1350);
|
||||
|
||||
/* Add 1337 msec twice more; make sure that any second rollover issues
|
||||
* worked. */
|
||||
@ -6044,6 +6047,8 @@ test_util_monotonic_time_add_msec(void *arg)
|
||||
monotime_coarse_add_msec(&ct2, &ct2, 1337);
|
||||
tt_i64_op(monotime_diff_msec(&t1, &t2), OP_EQ, 1337*3);
|
||||
tt_i64_op(monotime_coarse_diff_msec(&ct1, &ct2), OP_EQ, 1337*3);
|
||||
tt_int_op(monotime_coarse_diff_msec32_(&ct1, &ct2), OP_GT, 3970);
|
||||
tt_int_op(monotime_coarse_diff_msec32_(&ct1, &ct2), OP_LT, 4051);
|
||||
|
||||
done:
|
||||
;
|
||||
|
Loading…
Reference in New Issue
Block a user