I finally managed to beat the official client in some metrics! This means that performance is finally good enough for a release!!!
The big difference in the producer side was that MyNatsClient was calling Flush
for each send, while the official client was doing this on a separate thread.
There's some awesome constructs in the official client, like e.g. stashing away non flushed data in case of disconnect etc. which then is dispatched on reconnect (if any). I've chosen to go a more manual or simple way in not having Flush
being done in the background. Instead, by default it's done for each Publish
. How-ever, you can turn this off and flush your self. Lets have a look.
The default behaviour is PubFlushMode.Auto
, but you can switch this for Manual
:
var cnInfo = new ConnectionInfo(hosts) {
PubFlushMode = PubFlushMode.Manual //Default is Auto
};
Now, if you call Pub
there will only be a flush, if the BufferedStream
needs to, so to make sure that data is flushed, you need to call client.Flush()
or client.FlushAsync()
.
client.Pub("mysubject", "My message1");
client.Pub("mysubject", "My message2");
client.Flush();
There's is also client.PubMany
which will Flush
when buffer is full or when your injected delegate is done:
client.PubMany(p => {
p.Pub("mysubject", "My message1");
p.Pub("mysubject", "My message2");
});
//Here it will have been flushed
The PubMany
method will sync-lock around all calls to Pub
instead of for each call.
Metrics
So, running with PubFlushMode.Manual
and calling Flush
after each batch provided some far better metrics. I'm NOT using PubMany
in these timings.
Since we are sending string messages, the official client also includes the time for doing Encoding.UTF8.GetBytes(message)
which my client does underneath.
Also note, I'm not forcing a Flush
when using the official client, but instead letting it do it's background flush.
You can find the sample code for timing this in the repo:
Feel free to look into it and give me feedback on API etc.
Cheers,
//Daniel