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

Run 1

8.6

57

176

150

44

138

Run 2

7.7

54

172

52

40

133

Run 3

8.3

54

196

149

42

132

Run 4

8.2

54

203

151

40

130

General

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

.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.

Log Extension

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.

true Matcher

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.

false Matcher

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.

Exception

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:

n =

4

8

16

32

64

128

256

512

1024

2048

Run 1

224

214

68

77

223

213

187

9994

9955

9795

Run 2

199

205

72

72

257

207

196

9901

9972

9820

Run 3

234

203

74

73

218

204

197

9895

9990

9833

Run 4

207

259

67

69

221

205

194

10023

9963

9797

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.

Test Machine

Conclusions

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.

Great article and great library. I’m researching using it for a project of mine. It actually is a real-time program, but I think the 180,000 events /sec would be fine for my application. The 256 event wall you looks interesting, makes me curious as to what it is( I’ll have maybe 6 at most so I’m not worried.
Do you have more detailed example of how the async events would work ? I’d be interested to see an example of how you used it.
Thanks,
Jerry