Skip to content

Optimizing 'unreferenced' timers #16105

Closed
@Fishrock123

Description

@Fishrock123

tl;dr: Timer#unref() is not very efficient, and is also confusing. This should be fixable.

Timers use pooled handles behind the hood in all normal cases. There is one exception: if a timer has been unreferenced by using Timer#unref(). (But not _unrefActive, which pools the timer but also resets it.)

#8372 Is my pervious attempt at optimizing it. As noted in that PR, that method is very odd and IIRC probably also has some behvaior weirdness in slightly-edge-cases.

A better solution is outlined by @misterdjules in that issue. I am describing it below in clearer detail so that other may better understand it. It assumes basic knowledge of our timers algorithm/implementation, most of which can be found in the extensive comments near the top of lib/timers.js.

From #8372 (comment):

I wanted to experiment with another approach to making unrefed timers use TimerList instances, but without the inconsistency of having some of them not use TimersList.

Each TimersList could keep a counting tracker of how many unrefed timers it contains. This would be incremented / decremented whenever Timeout#unref() / Timeout#ref() are called, and also when unref timers call their callbacks. Whenever this counter is adjusted the implementation would check if there are unrefed timers, and then either unref or ref the TimerWrap handle accordingly.

Additionally, it could also cover _unrefActive, and pool our internal unreferenced timers without needed separate pools, even for the same duration.

The logic behind this revolves around the fact that unrefed handles don't matter if there are still refed handles.

Also, this means we wouldn't need separate _handle properties on unreferenced timers, which is honestly just a confusing behavior as it stands today.

The major consideration here is whether unrefing and re-refing a libuv handle has much overhead. My recollection was that it did not have significant overhead (from @trevnorris, I think), but that would need to be investigated alongside this. (See below.) Keep in mind timers is potentially hot code for any net request and does actually need to be quite efficient.

Metadata

Metadata

Assignees

Labels

help wantedIssues that need assistance from volunteers or PRs that need help to proceed.performanceIssues and PRs related to the performance of Node.js.timersIssues and PRs related to the timers subsystem / setImmediate, setInterval, setTimeout.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions