(Benchmark is at the bottom)
When creating diorite I needed to have some efficient and advanced event bus, one of best available for java is MBassador.
Performance of MBassador is great, but… there is few places that are just annoying and might later create performance issues that would be hard to fix.
Few basic problems od MBassador:
- Every event is called, even if there is 0 listeners to it: Github link
- Every published event always scan all subscriber of compatible type: Github link
- When publishing event it always scan for all super types, for complicated object with many long type hierarchy it can decrease performance, especially if event isn’t used as already mentioned above: Github link
So… instead of creating own event bus, I forked MBassador and changed it to fit into diorite project:
So I did few simple changes:
- Removed support for
Envelope
(multiple different message types in one listener) handlers to simplify dispatch process so further optimizations can be done. - Removed JUEL, and replaced it with groovy (with @CompileStatic for best performance)
- Removed weird and unused option that supports more than single handler method parameter while scanning.
- Added
Cancellable
interface andignoreCancelled
option in@Handler
to provide better support for diorite events. - Added cache of subscribers for each message type (cleared on ech new/removed subscriber, might be later improved to only clear changed types)
- Added cache of unused event types (also cleared on every change) must be first enabled by setting
useUnusedEvent
setting to false.
All changes can be found there: Github GotoFinal/mbassador
And now best part, benchmark:
Benchmark Mode Cnt Score Error Units
EventbusBenchmark.expensiveTypeEvent_goto avgt 3 66,885 ± 1,345 ns/op
EventbusBenchmark.expensiveTypeEvent_mbas avgt 3 1164,972 ± 21,078 ns/op
EventbusBenchmark.playerEvent_goto avgt 3 62,588 ± 3,987 ns/op
EventbusBenchmark.playerEvent_mbas avgt 3 451,340 ± 12,528 ns/op
EventbusBenchmark.somePlayerEvent_goto avgt 3 64,790 ± 2,772 ns/op
EventbusBenchmark.somePlayerEvent_mbas avgt 3 507,218 ± 24,855 ns/op
EventbusBenchmark.unusedEvent_goto avgt 3 7,004 ± 0,543 ns/op
EventbusBenchmark.unusedEvent_mbas avgt 3 235,144 ± 17,397 ns/op
And as you can see:
- publishing unused events is just invisible, only 7ns! (compared to old 235ns)
- performance of each publish is much better due to caching.
- performance isn’t affected by amount of super types in hierarchy.
And that will be everything for now, if someone also needs better performance for publishing events and unused ones, feel free to use this one!
If you want me to check something you can't understand, or explain some weird java behavior, feel free to e-mail me at: gotofinaldev@gmail.com or just write comment below!