]> git.ipfire.org Git - thirdparty/haproxy.git/commit
MINOR: clock: do not update the global date too often
authorWilly Tarreau <w@1wt.eu>
Wed, 21 Sep 2022 06:21:45 +0000 (08:21 +0200)
committerWilly Tarreau <w@1wt.eu>
Wed, 21 Sep 2022 07:06:28 +0000 (09:06 +0200)
commit4eaf85f5d92f8b3788c4f1f5060d5d3331cfe472
tree0a9f8628bc0dbe00acae041d520290accf67d938
parent58b73f9fa8a46b321e28478f9bb711ae7dc0630a
MINOR: clock: do not update the global date too often

Tests with forced wakeups on a 24c/48t machine showed that we're caping
at 7.3M loops/s, which means 6.6 microseconds of loop delay without
having anything to do.

This is caused by two factors:
  - the load and update of the now_offset variable
  - the update of the global_now variable

What is happening is that threads are not running within the one-
microsecond time precision provided by gettimeofday(), so each thread
waking up sees a slightly different date and causes undesired updates
to global_now. But worse, these undesired updates mean that we then
have to adjust the now_offset to match that, and adds significant noise
to this variable, which then needs to be updated upon each call.

By only allowing sightly less precision we can completely eliminate
that contention. Here we're ignoring the 5 lowest bits of the usec
part, meaning that the global_now variable may be off by up to 31 us
(16 on avg). The variable is only used to correct the time drift some
threads might be observing in environments where CPU clocks are not
synchronized, and it's used by freq counters. In both cases we don't
need that level of precision and even one millisecond would be pretty
fine. We're just 30 times better at almost no cost since the global_now
and now_offset variables now only need to be updated 30000 times a
second in the worst case, which is unnoticeable.

After this change, the wakeup rate jumped from 7.3M/s to 66M/s, meaning
that the loop delay went from 6.6us to 0.73us, that's a 9x improvement
when under load! With real tasks we're seeing a boost from 28M to 52M
wakeups/s. The clock_update_global_date() function now only takes
1.6%, it's good enough so that we don't need to go further.
src/clock.c