Open Jorropo opened 2 years ago
This doesn't seem to match the general model for io.Pipe
, which is that reads and writes are matched when possible.
This doesn't seem to match the general model for
io.Pipe
, which is that reads and writes are matched when possible.
I don't understand what this means.
I shouldn't have assumed this was obvious, but calls to WriteTo
and ReadFrom
would block until completion is received from the other side, exactly how Read
and Write
do it except it is sharing a Writer
and Reader
instead of []byte
.
What I mean is that io.Pipe
is designed so that every call to Write
matches a call to Read
, when possible. If you don't want that behavior, there isn't much reason to use io.Pipe
. So I think you're right that we could make io.Copy
of an io.Pipe
more efficient, but I don't understand how that would help any real program.
I think I get it now, it's that one call to write will always match one call to read (assuming the read buffer is big enough).
That seems to be a very special detail to me. When I use it, it's because I have poorly architectured code, one function wants to write the other one want to read (imagine using json.Encoder
with http.NewRequest
for example).
So I just throw an io.Pipe
and a goroutine at it because it require order of magnitude less time than implementing a lazily json serialiser that would serialise inside .Read
calls (for example, I don't often do that with json it's just an example, usually I use bytes.Buffer
, I have other GiBs big formats where streaming actually matters).
However io.Pipe
is not that fast for this and I was hopping to give it a bit more humpf (by skipping a copy for example).
Adding ReadFrom
and WriteTo
would not affect the 1 to 1 relationship of Write
and Read
.
Also ReadFrom
would also have a 1 to 1 relationship with Read
(altho it's more likely your buffer isn't big enough and you have to call multiple times).
There is opportunities to skip synchronization events, allocations and maybe even do some zero copies (if
WriteTo
andReadFrom
are called concurrently).If
ReadFrom
is called this would allowRead
to acquire a reference to theReader
passed in and pass the buffer slice to the reader directly (skipping a possible allocation that would have been required to copy data fromReader
toPipeWriter
). IfWriteTo
is called this would allowWrite
to acquire a reference to theWriter
passed in and pass the buffer slice to the reader directly (skipping a possible allocation that would have required to copy data fromPipeReader
toWriter
). IfReadFrom
andWriteTo
are called this would allow to callio.Copy
(or equivalent reusing a buffer) to maybe do a zero copy between theWriter
andReader
.The implementation would need to account for the fact that
ReadFrom
can be called multiple times andWriteTo
need to waits until the pipe is closed, but nothing that cannot be done.The extra channels required to pass the
Writer
andReader
around might be much in term of extra allocations, I guess async
based implementation (instead of channels) would be better (as it would just embed all synchronization primitives into thepipe
struct).