Foreign buffers are buffers not allocated with the Pipe MemoryPool.
Use-cases for foreign buffers:
Comments:
/cc @Drawaes
This actually used to exist - it was called Append, took a ReadOnlyBuffer, and it is sorely missed. Strictly speaking, the pipe doesn't need to care where it comes from - it just needs to Preserve when accepting it, and Release when it is done (it already does the Release step). If it goes back to a memory pool: great! if it was actually a wrapped non-owned array, or a chunk from a completely unrelated pool: also fine!
Use cases:
Utf8String)Without this, "zero copy" isn't possible.
To be honest if Foreign buffers are a problem initially, then okay. But at the very least buffers from the same pool should be append able. Imagine say a protocol that reframes, at the moment you have to copy all the data across from one pipe to the other with either a small header added or removed, so as @mgravell says Zero copy is killed here.
I would prefer foreign buffers could be allowed also.
Another scenario for Append is to "stage" writes. Only a single thread can be "writing" to a pipeline at a time, which is fine. However sometimes you can have multiple threads building frames, you then serialize the write. However without Append this adds a copy to the processing.
Example
High performance trading applications often "stage" a buy and sell frame ready to send for many stocks. When something makes the decision to actually buy or sell you want to be able to just "append" that pre generated buffer without copying straight to the socket (or as quick to the socket as you can).
Today you don't see this scenario with ASP.NET because it tends to be a single thread servicing a single request/response at a time, however in Service to Service communications often a single pipe is used by many backend threads, and you want to keep the serialization of these to a minimum.
This would be useful in Orleans where clients send request messages to a server which might then forward it on to the correct destination server. That's a common scenario for any distributed system which has a gateway/reverse proxy component (eg nginx, HAProxy, mongodb).
Currently we duplicate buffers when a message might be forwarded because of how our buffer pool works (no block-level ref counting). See https://github.com/dotnet/orleans/blob/a2e723da9b00638494c235f75fdca7c4fa8cb2e1/src/Orleans.Core/Messaging/IncomingMessageBuffer.cs#L181
Should this issue move to corefx repo?
Should this issue move to corefx repo?
Yes, please.
@tmds Closing this one. Please do the needful :)
Most helpful comment
/cc @Drawaes
This actually used to exist - it was called
Append, took aReadOnlyBuffer, and it is sorely missed. Strictly speaking, the pipe doesn't need to care where it comes from - it just needs toPreservewhen accepting it, andReleasewhen it is done (it already does theReleasestep). If it goes back to a memory pool: great! if it was actually a wrapped non-owned array, or a chunk from a completely unrelated pool: also fine!Use cases:
Utf8String)Without this, "zero copy" isn't possible.