Event Broker: a notification component for synchronous and asynchronous, loosely coupled event handling.
Therefore, I implemented a quick performance test application that prints out the timings for
- Plain .NET events
- Event over Event Broker
- Event over Event Broker with logging extension enabled
- Event over Event Broker with a matching matcher on the subscriber
- Event over Event Broker with a non-matching matcher on the subscriber
- Event over Event Broker with exception throwing subscriber
As well as how the number of subscribers on a single event influences timings.
See explanation of results for details on these scenarios.
Each test scenario above is executed once, giving the results for a “run”. Four runs are executed in total to get a picture of long time behaviour. The numbers show used milliseconds for 10’000 events. The timings for plain .NET are multiplied with a factor equal to 100 to make them visible in the graph.
|milliseconds||.NET * 100||Event Broker||Log Extension||true Matcher||false Matcher||Exception|
Initialization (event registration, publisher and subscriber instance creation) is not included in the timings. Only the time of firing the event and handling it with an empty handler is taken into account.
.NET events are very fast, you can execute over 16’000’000 events per second! To have a value in the graph I show the value scaled with a factor of 100.
Event Broker Events
The second column shows the time used to execute 10’000 events over the Event Broker. The event is always fired on the same publisher and received on the same subscriber.
On the test machine, I can execute over 180’000 event broker events per second.
The third column shows the time used when the log extension is added to the event broker. Please note that this includes preparing the log messages and calling log4net logger methods, but not actual logging because log4net is not configured.
As you can see, if you really need performance then do not add the log extension or use your own logging extension that only logs what you really need.
In this scenario, I added a matcher on the subscriber that always matches – meaning that the event is relayed to the subscriber and the handler method on the subscriber is executed.
As you can see, executing matcher – even if as simple as just returning true – is quite expensive. Therefore, you should only use matchers when really needed.
When using a matcher on the subscriber that never matches, the execution time shrinks because the event is not relayed to the subscriber and the handler method on the subscriber is not called.
In this scenario, the subscriber throws an exception. As you can see, exception handling is not that expensive in .NET.
Dependency On Number Of Subscribers
The following table and graph shows the execution time of 10’000 events over the event broker from a single publisher to n subscribers:
You see the time used to execute 10’000 times the same event over the event broker (without logging, matchers, exceptions).
Up to 256 subscribers, the execution time is more or less the same – what surprised me a lot by the way. For more than 256 subscribers the timings change dramatically. Again, only a profiler could solve this mystery. However, my best guess is that something in memory management changes when 256 subscribers are present.
In real life however, the number of subscribers is normally small per event topic.
Dell XPS M1330, Intel® Core(TM)2 Duo CPU T7500 @ 2.20 GHz, 4.00 GB RAM, Windows Vista 32 bit
How you interpret this numbers is up to you. For me, they show that the event broker implementation is fast if you take the features you get into account. Therefore, whenever you do not want to miss the loose coupling power that event broker brings you then use it.
Finally, some numbers are very surprising – needing further investigation. But this has to wait for another post.