EventBus icon indicating copy to clipboard operation
EventBus copied to clipboard

Skip phase tracking notifiers at registration time rather than post time

Open PaintNinja opened this issue 11 months ago • 5 comments

This removes the need for additional checks per listener when posting.

PaintNinja avatar Jan 16 '25 22:01 PaintNinja

I genuinely don't know how to test this. EventBus is still really foreign to me. But the code looks sane. I'll leave this to Lex.

Jonathing avatar Jan 23 '25 16:01 Jonathing

TLDR the PR is marked as a draft with minimal explanation because I was trying to troubleshoot what turned out to be a JVM bug.

Allow me to elaborate what this PR does and how...

First off, EventBus has a feature called "phase tracking" - this is basically telling events what priority they're in, which is used to prevent cancelling during the monitor phase. It does this by adding extra listeners for each priority that run just before the user defined listeners.

Currently, the phase tracking notifiers are always registered, even if the EventBus they're associated with has phase tracking disabled. To effectively disable these notifiers, it does an if check and class comparison for every listener on every post.

This PR makes it so that if check is unnecessary as it instead lets the ListenerListInst know if phase tracking is wanted during registration time. It skips adding the phase tracking notifiers to the listener list entirely when it knows they're not wanted, rather than checking every listener at post time.

In theory this should provide a nice performance uplift to posting, as it decreases the array size returned by the getListeners() method, makes the loop more predictable to the JIT and reduces the amount of work to do on each iteration.

In practice, posting a single listener is faster with this PR but posting hundreds is counter-intuitively slower. I have absolutely no idea why and at this point I'm convinced it's a JVM bug.

To test this, run the JMH task with gradlew jmh -Pbench="BenchmarkModLauncher.Posting.Static.postStatic" both on the master branch and this PR branch. You can throw a println(listeners.length) in the EventBus#post method and disable phase tracking in ModLauncherBenchmarks/BenchmarkModLauncher by adding setPhaseTracking(false) in the BusBuilder call where the bus is created to see the number of listeners reduce vs when phase tracking is enabled.

PaintNinja avatar Jan 23 '25 17:01 PaintNinja

That's rough

Jonathing avatar Jan 23 '25 17:01 Jonathing

I have a suspission it has to do with the field becoming package private and list.phaseTracking not being final. Perhaps a better approach would be to change the ListenerList.resize function take in the eventbus/phaseTracking boolean. This was the check is done once at list creation and can be finalized.

LexManos avatar Jan 23 '25 18:01 LexManos

Superseded by #69, which completely redesigns EventBus. Re-open if you want this as a candidate for a 6.2 release.

Jonathing avatar Mar 19 '25 21:03 Jonathing