Avoid "hot idle": A series of rapid select() calls with zero timeout.
Squid uses "infinite" precision when it comes to deciding whether the next
timed event is ready but uses millisecond (1e-3) precision when deciding how
long to wait before the next event will be ready. This inconsistency results
in the EventScheduler engine telling the main loop that it has 0 milliseconds
to poll pending I/O, but when asked again (after the I/O is quickly polled),
the EventScheduler engine often does not schedule the promised event and tells
the main loop to poll for another 0 milliseconds again. This cycling may
happen many times in a row (until enough time is wasted for the next event to
become ready using higher precision).
The fixed code adds a minimum 1ms delay for not-yet-ready events. It also
places both decisions into one method (EventScheduler::timeRemaining), and
tries to polish/document decision logic (which is more complex than it may
seem) because the code has to avoid both inconsistent decisions and hot idle
loops while maintaining the traditional "no event is fired before it is due"
guarantee.
TODO: Idle Squid still runs hotter than it should because the maximum waiting
time is artificially capped outside the event queue to EVENT_LOOP_TIMEOUT=1s.
This causes at most one extra loop iteration per second.