rabbitmq / rabbitmq-dotnet-client

RabbitMQ .NET client for .NET Standard 2.0+ and .NET 4.6.2+
https://www.rabbitmq.com/dotnet.html
Other
2.1k stars 586 forks source link

Investigate how other .NET client libraries deal with data from applications #1446

Open lukebakken opened 11 months ago

lukebakken commented 11 months ago

Reference:

https://github.com/rabbitmq/rabbitmq-dotnet-client/pull/1445

In that PR, BasicPublishAsync is modified to conditionally copy data from the client application. @paulomorgado then followed up with this comment.

Someone should take a look at libraries like these to see what is done in this scenario:

paulomorgado commented 11 months ago

We need to be careful with comparisons here.

If you think about stream operations, they don't copy the whole message (or any part of it). It's the responsibility of the caller to not modify that memory.

Microsoft.Data.SqlClient allows some columns to be read as Stream. (see SqlDataReader.GetStream(Int32) Method). No way to write parameter values as Stream, though.

But both SqlDataReader and SqlParameter can work with SqlBytes that provide direct access to different byte sources/destinations.

APIs are becoming more mindful of memory usage and taking advantage of the new types introduced to avoid memory allocation and copying.

If other libraries are not doing the same, maybe they should.

stebet commented 7 months ago

I really like how the new NATS .NET Client v2 does things for (de)serializing data. Take a look at this: https://nats-io.github.io/nats.net.v2/documentation/serialization.html

By default they both accept and return a NatsMemory object which is an IDisposable object that takes care of renting/returning memory, which is then automatically done when the objects go out of scope if it hasn't been manually dispose with for example a using block. This is similar to how MemoryOwner<T> works in the core runtime and makes it easy to use memory efficiently. They also do not buffer commands to the server with a Channel, but just write struct objects/commands directly to the Pipelines.

It's pretty impressive in it's low memory overheads without sacrificing usability or making it easy to hang on to memory too long.