-
Notifications
You must be signed in to change notification settings - Fork 18k
io: Copy() unnecessarily allocates memory when src is a file and is empty #53658
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
Labels
FrozenDueToAge
NeedsInvestigation
Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Milestone
Comments
Change https://go.dev/cl/415834 mentions this issue: |
cc @griesemer |
Change https://go.dev/cl/536455 mentions this issue: |
gopherbot
pushed a commit
that referenced
this issue
Oct 23, 2023
…ith 0 bytes sent CL 415834 fixed #53658 and somehow it only fixed it on Linux, sendfile can also succeed with 0 bytes sent on other platforms according to their manuals, this CL will finish the work that CL 415834 left out on other platforms. goos: darwin goarch: arm64 pkg: net │ old │ new │ │ sec/op │ sec/op vs base │ SendfileZeroBytes-10 7.563µ ± 5% 7.184µ ± 6% -5.01% (p=0.009 n=10) │ old │ new │ │ B/op │ B/op vs base │ SendfileZeroBytes-10 3562.5 ± 7% 590.0 ± 2% -83.44% (p=0.000 n=10) │ old │ new │ │ allocs/op │ allocs/op vs base │ SendfileZeroBytes-10 0.00 ± 0% 11.00 ± 0% ? (p=0.000 n=10) [1] https://man.freebsd.org/cgi/man.cgi?sendfile(2) [2] https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/sendfile.2.html [3] https://man.dragonflybsd.org/?command=sendfile§ion=2 [4] https://docs.oracle.com/cd/E88353_01/html/E37843/sendfile-3c.html Change-Id: I55832487595ee8e0f44f367cf2a3a1d827ba590d Reviewed-on: https://go-review.googlesource.com/c/go/+/536455 Auto-Submit: Bryan Mills <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Bryan Mills <[email protected]>
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Labels
FrozenDueToAge
NeedsInvestigation
Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Ye.
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
This affects
io.Copy()
when src is a file, and dst is a*net.TCPConn
.Here is a minimal benchmark: https://go.dev/play/p/zgZwpjUatSq
Benchmark with
go test -bench=. -benchmem
Summary is that a gorotoutine writes to a file, another goroutine reads from the file and writes it to a TCPConn with io.Copy(). io.Copy tries to be efficient and will try to use
sendfile(2)
, however it doesn't always succeed and ends up allocating a buffer anyway. In my deubgging it turns out the current logic believessendfile(2)
failed if we written 0 bytes. Using benchmark above one can see that we allocate 5KB/op, where op is writing a single byte.This also affects
io.CopyBuffer()
, when we fail to usesendfile(2)
(in case of empty src) it falls back toio.Copy(writerOnly{w}, r)
which ignores passed in buffer and allocates its own.What did you expect to see?
CopyBuffer
always uses passed in buffer,Copy
does not allocate extra buffer when src is empty.What did you see instead?
Running the benchmark above shows 5GB was allocated to transfer 0.5MB worth of data, due to allocating a buffer (see
size := 32 * 1024
below) when it wasn't necessary (sendfile(2)
tried to copy, but there was nothing to copy).The text was updated successfully, but these errors were encountered: