Rework TImerThread's timer storage to allow in-order access
Categories
(Core :: XPCOM, task)
Tracking
()
Tracking | Status | |
---|---|---|
firefox111 | --- | fixed |
People
(Reporter: mozbugz, Assigned: jlink)
References
Details
Attachments
(16 files, 13 obsolete files)
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review |
TimerThread::mTimers
is currently an array of unique pointers to Entry
's, managed as a binary heap (with std::push_heap
and std::pop_heap
, such that the first element always has the earliest timeout).
This arrangement was implemented in bug 1325254, and makes adding timers very fast, but makes it difficult to look at multiple timers in order, which will be needed when trying to coalesce timers in bug 1783405.
This bug intends to change mTimers into a sorted array of entries.
I will attach the current WIP soon, but I won't have the time to finish it together with bug 1783405 (it doesn't make much sense to do one without the other.)
Testing it showed that the overall speed was pretty much the same.
While adding elements in a sorted array is intuitively slower than using std::push_heap
, this was effectively balanced by a number of factors:
- The list is generally fairly small, tens to around 100 elements at times, so linear access is fast on modern CPUs thanks to cache locality and prefetching.
- Storing entries instead of pointers to on-memory-heap entries, saving lots of (de)allocations and indirections.
- Removing timers is done by nulling a pointer in entries, and when adding we can reuse these "empty" entries (either directly, or when inserting and therefore moving elements to the right until the first empty entry), resulting in few element moves in practice.
Reporter | ||
Updated•2 years ago
|
Reporter | ||
Comment 1•2 years ago
|
||
This adds more information in the "AddTimer" markers, about the internal state
of the TimerThread when adding each timer.
Reporter | ||
Comment 2•2 years ago
|
||
Also both AddTimer and RemoveTimer markers now show the duration of these
function calls.
Depends on D155932
Reporter | ||
Comment 3•2 years ago
|
||
Depends on D155933
Reporter | ||
Comment 4•2 years ago
|
||
Depends on D155934
Reporter | ||
Comment 5•2 years ago
|
||
Note that it's about 4 times slower in practice! But this will be balanced in later patches.
Depends on D155935
Reporter | ||
Comment 6•2 years ago
|
||
nsTimerImplHolder can now be removed.
Depends on D155936
Reporter | ||
Comment 7•2 years ago
|
||
This removes memory heap allocations and deallocations, and indirections to access entries.
Depends on D155937
Reporter | ||
Comment 8•2 years ago
|
||
So entries now store the given timeout value (instead of clamping it to after "now").
And we store this timeout first, as it's accessed more frequently.
Depends on D155938
Reporter | ||
Comment 9•2 years ago
|
||
Depends on D155939
Reporter | ||
Comment 10•2 years ago
|
||
Depends on D155940
Reporter | ||
Comment 11•2 years ago
|
||
Inserting elements in the sorted array is more costly than pushing to a binary
heap, but this is balanced by the removal of indirections and de/allocations,
and the upcoming re-use of empty entries.
In the end, this change is necessary to allow future improvements like timer-
coalescing, where we'll need to see multiple timers in order.
Bonus: FindNextFireTimeForCurrentThread changes a lot, because it used to have
to pop_heap
elements and then push_heap
them back! (Sometimes resulting in
subtle changes for timers with the same timeout.) So this one benefits the
most.
Depends on D155941
Reporter | ||
Comment 12•2 years ago
|
||
This makes the code more complex, but it is needed to keep this most-used
function efficient related to its old implementation using std::push_heap
.
Depends on D155942
Reporter | ||
Comment 13•2 years ago
|
||
This adds some valuable markers showing the times from adding to dispatching a
timer, and then from dispatching to actually running the timer code.
Depends on D155943
Updated•2 years ago
|
Reporter | ||
Comment 14•2 years ago
|
||
Time is almost up for me, so I won't have time to progress this further myself. Happy to answer any questions though.
Good continuation, I hope this proves to be useful.
Assignee | ||
Updated•2 years ago
|
Assignee | ||
Comment 15•2 years ago
|
||
This adds more information in the "AddTimer" markers, about the internal state
of the TimerThread when adding each timer.
Assignee | ||
Comment 16•2 years ago
|
||
Also both AddTimer and RemoveTimer markers now show the duration of these
function calls.
Depends on D164281
Assignee | ||
Comment 17•2 years ago
|
||
Depends on D164282
Assignee | ||
Comment 18•2 years ago
|
||
Depends on D164283
Assignee | ||
Comment 19•2 years ago
|
||
Note that it's about 4 times slower in practice! But this will be balanced in later patches.
Depends on D164284
Assignee | ||
Comment 20•2 years ago
|
||
nsTimerImplHolder can now be removed.
Depends on D164285
Assignee | ||
Comment 21•2 years ago
|
||
This removes memory heap allocations and deallocations, and indirections to access entries.
Depends on D164286
Assignee | ||
Comment 22•2 years ago
|
||
So entries now store the given timeout value (instead of clamping it to after "now").
And we store this timeout first, as it's accessed more frequently.
Depends on D164287
Assignee | ||
Comment 23•2 years ago
|
||
Depends on D164288
Assignee | ||
Comment 24•2 years ago
|
||
Depends on D164289
Assignee | ||
Comment 25•2 years ago
|
||
Inserting elements in the sorted array is more costly than pushing to a binary
heap, but this is balanced by the removal of indirections and de/allocations,
and the upcoming re-use of empty entries.
In the end, this change is necessary to allow future improvements like timer-
coalescing, where we'll need to see multiple timers in order.
Bonus: FindNextFireTimeForCurrentThread changes a lot, because it used to have
to pop_heap
elements and then push_heap
them back! (Sometimes resulting in
subtle changes for timers with the same timeout.) So this one benefits the
most.
Depends on D164290
Assignee | ||
Comment 26•2 years ago
|
||
This makes the code more complex, but it is needed to keep this most-used
function efficient related to its old implementation using std::push_heap
.
Depends on D164291
Assignee | ||
Comment 27•2 years ago
|
||
This adds some valuable markers showing the times from adding to dispatching a
timer, and then from dispatching to actually running the timer code.
Depends on D164292
Assignee | ||
Comment 28•2 years ago
|
||
Depends on D164293
Updated•2 years ago
|
Updated•2 years ago
|
Updated•2 years ago
|
Updated•2 years ago
|
Updated•2 years ago
|
Updated•2 years ago
|
Updated•2 years ago
|
Updated•2 years ago
|
Updated•2 years ago
|
Updated•2 years ago
|
Updated•2 years ago
|
Updated•2 years ago
|
Updated•2 years ago
|
Updated•2 years ago
|
Updated•2 years ago
|
Updated•2 years ago
|
Updated•2 years ago
|
Updated•2 years ago
|
Updated•2 years ago
|
Updated•2 years ago
|
Updated•2 years ago
|
Updated•2 years ago
|
Updated•2 years ago
|
Updated•2 years ago
|
Updated•2 years ago
|
Updated•2 years ago
|
Updated•2 years ago
|
Assignee | ||
Comment 29•2 years ago
|
||
I also took a stab at documenting the behavior since I found it a bit
difficult to follow.
Depends on D164294
Updated•2 years ago
|
Assignee | ||
Comment 30•2 years ago
|
||
Due to the possible presence of canceled timers at the "front" of the
list, mTimers[0] won't necessarily hold the next timer to be fired
unless we've cleaned up those front timers recently.
Assignee | ||
Comment 31•2 years ago
|
||
Try run with the current patch stack: https://treeherder.mozilla.org/jobs?revision=eba0461bc280f88e1d42ff0a95e45468542517ad&repo=try (seems good to me)
Updated•2 years ago
|
Updated•2 years ago
|
Updated•2 years ago
|
Assignee | ||
Comment 32•2 years ago
|
||
Olli, Florian: I've moved the three changes with the "top" of the stack and made sure that each change in the new stack compiles (with its dependent changes). I've also now disconnected the profiling changes from the rest of the stack as well.
It looks like all of the non-profiling changes have been approved so I'll probably try to land this a little later today unless you let me know and want to take one last look first. (I think I still have a few code review comments to respond to/close also.)
Comment 33•2 years ago
|
||
Comment 34•2 years ago
|
||
bugherder |
https://hg.mozilla.org/mozilla-central/rev/e22855795b9f
https://hg.mozilla.org/mozilla-central/rev/aad44174c4bf
https://hg.mozilla.org/mozilla-central/rev/5d58bb968292
https://hg.mozilla.org/mozilla-central/rev/b70b44f7828f
https://hg.mozilla.org/mozilla-central/rev/248126e639c3
https://hg.mozilla.org/mozilla-central/rev/cc9b47f124a8
https://hg.mozilla.org/mozilla-central/rev/6603be788d60
https://hg.mozilla.org/mozilla-central/rev/4c8d9ee64409
https://hg.mozilla.org/mozilla-central/rev/115dff277414
https://hg.mozilla.org/mozilla-central/rev/facb9344bb5d
https://hg.mozilla.org/mozilla-central/rev/f1f071954863
https://hg.mozilla.org/mozilla-central/rev/199888078547
https://hg.mozilla.org/mozilla-central/rev/3e5c9fa28ebb
Description
•