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), orvcbuild test
(Windows) passes -
commit message follows commit guidelines
Affected core subsystem(s)
events