Skip to content

Conversation

@cmeissl
Copy link
Contributor

@cmeissl cmeissl commented Feb 10, 2026

A client cancelling and inserting timers at high rates could result in the used heap to grow unexpectedly.
This can for example happen if a compositor tracks inactivity using a timer and receives a lot of pointer events in a single dispatch.

Currently TimerWheel::cancel can result in just marking a timer cancelled without the timer being actually removed
from the heap. So there might be a time-frame where the heap grows quite big holding mostly cancelled timers.
TimerWheel::next_expired is expected to clean-up the cancelled timers, but at this point the heap might have already
grown quite big and BinaryHeap::pop will not implicitly shrink its backing store.
Also I am not completely sure this will catch all usage patterns as TimerWheel::insert could result in re-ordering
of the heap.
(Note: Calling shrink might also bring the memory consumption down, but this might result in constant re-allocation)

Calling TimerWheel::cancel might already result in linear search in the heap to mark a timer cancelled,
so imo using retain does not make this worse but should keep the heap at a reasonable size.
This might also have the side-effect of making some operations like next_expired a bit faster for some use-cases.

fixes #233

since rust 1.70 BinaryHeap provides a retain
function that can be used to remove our
cancelled timers.
this prevent indefinitely grow of the heap
when timers get cancelled and re-inserted
with high frequency.
now that we always clean-up cancelled timers
right away there is no longer a need to store
the token in an Option.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Timer::unregister() taking longer and longer as session time increases

1 participant