From #6050:
The Dispatcher runs a single batch-flush timer that is armed unconditionally
and reset on every fire, regardless of whether any batch actor has buffered
messages. Because each Publisher owns its own Dispatcher, an application with
many publishers performs continuous timer work even when completely idle. In
Dispatcher::run the timer is created once, and on every delay_threshold
interval it flushes all batch actors and then re-arms itself unconditionally,
so an idle publisher keeps scheduling and servicing a timer with nothing to
send. At high publisher cardinality this becomes a constant source of
time-wheel work; we observed it dominating idle CPU in a production service
that fans a single logical publisher out across several thousand topics.
For reference, the Java client's Publisher.setupAlarm only schedules the
alarm while a batch is non-empty and cancels it once the batch drains, so it
holds no timer at rest. This change brings the Rust client in line with that
behavior.
From #6050: