-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Async all the way #3
base: main
Are you sure you want to change the base?
Conversation
Currently, this is a pretty-complete ValueTask-based async-implementation of the RabbitMQ client. Allocations have been reduced even further, and some pretty hefty performance gains as well in my tests at least. This currently compiles and almost all tests run (one fails which might be obsolete with an async client) but there is some cleanup to be done yet. |
I have yet to write up a bigger description of the functional changes although public API changes other than operations being async are minimal. This takes advantage of |
Made this work :) Now targets .NET Standard 2.0 |
Need to look in more details. One initial question though: What's the reason you went with
https://devblogs.microsoft.com/dotnet/understanding-the-whys-whats-and-whens-of-valuetask/ Isn't most of the public API here more a candidate for |
Quite right, a lot of it is. And that's one of the things to look at in more detail. There are conflicting views on this however: https://blog.marcgravell.com/2019/08/prefer-valuetask-to-task-always-and.html and @mgravell makes a lot of good points there. It's an interesting dilemma. Basically, whenever you might have an async method execute synchronously (obviously the RPC methods should never do that, but a lot of the System.IO.Pipelines based serialization/flushing does) you'd want to use a ValueTask. Also ValueTasks are more easily reusable to reduce allocations than Tasks (via. ManualResetValueTaskSourceCore). Consumers should be none-the-wiser really, unless they actually are awaiting more than once, which should really be a no-no, but that's me making a lot of assumptions. I have yet to do benchmarks and tests on what happens if we change the public facing async methods to Task (where appropriate). |
B.t.w, we could also PR this into a separate branch on the main repo if you'd like to get this code there for further work/review in a more official way @lukebakken @michaelklishin. |
@stebet that's a great idea. Talk about a lot of work here! I've added you as a contributor to the main repo so feel free to start a branch there with these changes. |
Will do :) |
Rebased and squashed the changes before initial PR to new branch. |
Initial async implementation. Decided to put this up here and add some collaborators, instead of polluting the main RabbitMQ repo with a not-yet-completed, long-running PR. Also to spark some discussions on how feasible this is as a major change, or if it would simply make more sense to release a completely different package with the async version due to the amount of breaking changes involved.
List of interesting changes:
ModelBase.cs - https://github.com/stebet/rabbitmq-dotnet-client/pull/3/files#diff-b5b88775d543e4647d83cd30a6909bd1
SocketFrameHandler.cs - https://github.com/stebet/rabbitmq-dotnet-client/pull/3/files#diff-d56528b89584ed384b8cd4125d4f2abd
Connection.cs - https://github.com/stebet/rabbitmq-dotnet-client/pull/3/files#diff-505de50e6370e0c153328803cd1a5db4
Frame.cs - https://github.com/stebet/rabbitmq-dotnet-client/pull/3/files#diff-4a1f7dd804ba9e80bcd236f26e37687d
RpcContinuationQueue.cs - https://github.com/stebet/rabbitmq-dotnet-client/pull/3/files#diff-7fde3385e9c372a542f70b25dc2f7429
Current allocation statistics from my benchmark app (down from 65mb -> 49mb) compared to data in rabbitmq#855: