Optimize Emitter.fire for 0 and 1 listeners

Before:
      Context "Emitter.fire()"
         Context "0 listeners"
            Case "#1" : 1 runs - average throughput: 97.77 MB/s
         Context "1 listener"
            Case "#1" : 1 runs - average throughput: 49.30 MB/s
         Context "2 listeners"
            Case "#1" : 1 runs - average throughput: 35.37 MB/s
         Context "5 listeners"
            Case "#1" : 1 runs - average throughput: 15.32 MB/s

After:
      Context "Emitter.fire()"
         Context "0 listeners"
            Case "#1" : 1 runs - average throughput: 376.94 MB/s
         Context "1 listener"
            Case "#1" : 1 runs - average throughput: 84.29 MB/s
         Context "2 listeners"
            Case "#1" : 1 runs - average throughput: 32.36 MB/s
         Context "5 listeners"
            Case "#1" : 1 runs - average throughput: 15.93 MB/s
This commit is contained in:
Daniel Imms
2026-01-31 14:42:23 -08:00
parent 21e4301e38
commit 042bb4bed9
3 changed files with 158 additions and 4 deletions
+14 -4
View File
@@ -53,10 +53,20 @@ export class Emitter<T> {
if (this._disposed) {
return;
}
// Snapshot listeners to allow modifications during iteration
const listeners = this._listeners.slice();
for (const { fn, thisArgs } of listeners) {
fn.call(thisArgs, event);
switch (this._listeners.length) {
case 0: return;
case 1: {
const { fn, thisArgs } = this._listeners[0];
fn.call(thisArgs, event);
return;
}
default: {
// Snapshot listeners to allow modifications during iteration (2+ listeners)
const listeners = this._listeners.slice();
for (const { fn, thisArgs } of listeners) {
fn.call(thisArgs, event);
}
}
}
}