(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 and ignoreCancelled 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!