Skip to content
This repository was archived by the owner on Apr 22, 2023. It is now read-only.
This repository was archived by the owner on Apr 22, 2023. It is now read-only.

http/net: _unrefActive() is extremely expensive #8160

@bnoordhuis

Description

@bnoordhuis

This probably affects master as well but I'm reporting this for v0.10. With any HTTP-heavy benchmark, exports._unrefActive() from lib/timers.js shows up high on the list of cost centers. Case in point:

1496   10.4%  LazyCompile: *exports._unrefActive timers.js:431
 607   40.6%    LazyCompile: *onread net.js:496
 579   38.7%    LazyCompile: *Socket._write net.js:619
 554   95.7%      LazyCompile: *Writable.write _stream_writable.js:163
 554  100.0%        LazyCompile: *Socket.write net.js:612

NB: That's from an application that puts together a multi-kilobyte SOAP response. That's an expensive operation but _unrefActive() still manages to dominate the list of most expensive functions.

There are two issues here, I think:

  1. The efficiency of _unrefActive()'s implementation leaves much to be desired.
  2. lib/net.js frequently calls _unrefActive() an ungodly number of times (for just about every I/O operation, something that really hurts with busy connections.)

I'd like to start a discussion on how to best fix that.

For 1, stripping _unrefActive() from unnecessary cruft seems like a first good step, maybe followed by switching to a timer wheel.

For 2, I'm less sure; the easiest solution I can think of (that is still provably correct and performs well) is to replace the timers._unrefActive(this) calls with something like this.nevents += 1. Then, when the timer expires:

  1. Check if this.nevents > 0.
  2. If true, restart the timer.
  3. If false, emit the timeout event.

That should greatly reduce the frequency of the (linear) scan over the timer list.

Thoughts, @indutny and @tjfontaine and anyone else who wants to chime in?

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions