Skip to content

events: several perf related adjustments

This PR covers a few different perf related changes to EventEmitter. Everything is separated into stand-alone commits. Might be easier to review as such but overall there actually there aren't that many lines being changed so it should be pretty easy to get through.

All performance benchmarks cited below are based on 100 or 200 sets (as necessary to get the right certainty) and are independent of other changes within the PR (so something like the onceWrapper result is strictly for that change and does not include the changes that precede it).

Feedback & reviews greatly appreciated!

events: stricter prop & variable checks for perf

Replace truthy/falsey checks of EventEmitter.prototype._events and EventEmitter.prototype._events[type] with comparisons to undefined for better performance:

events/ee-add-remove.js n=250000    5.30 %    *** 4.260028e-07
events/ee-emit.js n=2000000         4.18 %    *** 1.026649e-05

This has a knock-on effect on modules that use lots of events, e.g.:

http2/headers.js nheaders=0 n=1000  2.60 %    *** 0.000298338

It's possible this could affect user-land code if users are interacting with _events directly. We should strongly consider running CITGM. Maybe this is semver-major? Not sure since it's not documented and leading _ obviously signifies a private prop.

events: remove unnecessary console instantiation

Previously, console had to be compiled in case it was not available but this is no longer necessary - remove it.

Refs: #15111

events: return values directly in listeners

Each conditional branch in EventEmitter.prototype.listeners assigns its return value to a variable ret which is returned at the end. Instead just return from within each branch. This is both clearer and more performant.

events/ee-listeners.js n=5000000      3.65 %        *** 3.359171e-10

events: use spread function param in emit

With recent changes in V8, it is now as performant or faster to use spread parameter within EventEmitter.prototype.emit, especially in cases where looping over arguments is required.

events/ee-emit.js n=2000000               4.40 %    *** 1.505543e-06
events/ee-emit-1-arg.js n=2000000         2.16 %    *** 2.434584e-10
events/ee-emit-2-args.js n=2000000        1.05 %     ** 0.001764852
events/ee-emit-3-args.js n=2000000        2.18 %    *** 3.234954e-08
events/ee-emit-6-args.js n=2000000       17.17 %    *** 1.298702e-103
events/ee-emit-10-args.js n=2000000      17.14 %    *** 1.144958e-97

This has a knock-on effect for modules that use events extensively, such as http2:

http2/headers.js nheaders=0 n=1000        2.10 %    *** 6.792106e-11

events: onceWrapper apply directly with arguments

Due to changes in V8, it's no longer necessary to copy arguments to avoid deopt. Just call apply with arguments. Retains fast cases for 0-3 arguments.

events/ee-once-4-args.js n=20000000     11.58 %      *** 1.310379e-05
Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • commit message follows commit guidelines
Affected core subsystem(s)

events

Merge request reports

Loading