-
Notifications
You must be signed in to change notification settings - Fork 17.8k
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
proposal: io: Add io.ReaderFromBuffer interface #58331
Comments
See also #16474. |
The core issue is that the extended interface is always called if it exists. What one wants is a mechanism like errors.Unwrap or http.ResponseController.Unwrap or fs.ErrNotImplemented to signal that the method doesn't actually implement a direct ReaderFrom/WriterTo and shouldn't be used in a particular case. |
Thanks for the context @ianlancetaylor! just thinking out..
@carlmjohnson It does make sense to me. However, agree with the comment #16474 (comment) here:
Considering v2 might not exist ever, to me at least, having something that is non-breaking yet making Also interestingly mentioned here #16474 (comment)
this is actually what this proposal about, but in a non API breaking way. there are two usecase of
io.CopyBuffer(struct{ io.Writer }{dst}, struct{ io.Reader }{src}, buf)
Now there are two scenarios to this,
Bottomline, having |
Just starting returning |
|
Yes. I wrote on #41198 that the proposal is flawed because “ErrNotSuported” is domain specific. Not supporting http.FlushError is different than not supporting io.ReaderFrom. An overhaul of io.Copy should have io-specific ErrNotSupported variables. |
Change https://go.dev/cl/475575 mentions this issue: |
When calling
io.CopyBuffer(writer, reader, buf)
, it tries to use theio.ReaderFrom
interface onwriter
if it is available. For examplenet.TcpConn
implemets theio.ReaderFrom
and will try to use syscalls likesplice
orsendfile
to avoid additional copy in the user space.This is all well-intended and provides better performance in the case of copying from one net conn to another. However. If the
reader
is not a real file, but just some struct implementsio.Reader
, it actually falls back to usingio.Copy
.This is problem-some, as the very intention of using
io.CopyBuffer
is that we get to control the buffer and potentially pool the buffers to avoid GCs. But the generic fallback toio.Copy
makes the buffer passed in useless and makes an additional allocation.This behavior is clearly shown in the following heap profile (left is the buffer passed in, right is the allocation made by genericReadFrom fallback (io.Copy)):
This is a very surprising behavior to the end developers without the understanding of TcpConn readfrom internals. As an obvious optimization of using io.CopyBuffer in the hot-path turns out to be even worse than just call io.Copy.
So would propose to add an interface similar to io.ReaderFrom, but allows to take additional buffer, thus the name
io.ReaderFromBuffer
. This way nice optimization regarding fd copies can still happen, but in case none applies, the genericReadFrom can fallback toio.CopyBuffer
instead ofio.Copy
, to take advantage of the buffer passed in, if there is any.The text was updated successfully, but these errors were encountered: