-
Notifications
You must be signed in to change notification settings - Fork 18k
net/http: use Copy in ServeContent if CopyN not needed #65106
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
base: master
Are you sure you want to change the base?
net/http: use Copy in ServeContent if CopyN not needed #65106
Conversation
This allows some optimizations made in Copy to kick-in, like the use of io.WriterTo.
This PR (HEAD: cc9afa5) has been imported to Gerrit for code review. Please visit Gerrit at https://go-review.googlesource.com/c/go/+/555855. Important tips:
|
Message from Gopher Robot: Patch Set 1: (1 comment) Please don’t reply on this GitHub thread. Visit golang.org/cl/555855. |
Message from Leo Antunes: Patch Set 1: (1 comment) Please don’t reply on this GitHub thread. Visit golang.org/cl/555855. |
although the excelent benchmark by @AlexanderYastrebov seemed to indicate the underlying issue was solved, the higher-level benchmark by @mauri870 still shows a measurable slowdown (though not quite on the same level as originally observed; tested on current
Since the original syntetic benchmarks remain promising, this looks like another negative interaction with I'll draft this PR while I investigate further. Sorry for the noise. |
Longer: The benchmark results above are skewed by the using The overhead is then caused by missing the optimization in
Adding adapted benchmark code
func BenchmarkFileServe(b *testing.B) {
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "./go61530.test") // file size > 32k
})
r, _ := http.NewRequest("GET", "/file", http.NoBody)
rw := recorderWithReaderFrom{httptest.NewRecorder()}
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
handler.ServeHTTP(rw, r)
rw.Body.Reset()
}
}
type recorderWithReaderFrom struct {
*httptest.ResponseRecorder
}
// ReadFrom implements io.ReaderFrom.
func (rr recorderWithReaderFrom) ReadFrom(r io.Reader) (n int64, err error) {
return rr.Body.ReadFrom(r)
}
This means this PR shouldn't harm performance for the |
AFAICT the PR should actually improve performance for the realistic |
This PR (HEAD: 88ec1fb) has been imported to Gerrit for code review. Please visit Gerrit at https://go-review.googlesource.com/c/go/+/555855. Important tips:
|
With the latest commit the regression is solved. We now see a working However, since there are currently multiple proposals open around the intersection of Alternatively, we could also add an internal interface that is only implemented by |
Message from Damien Neil: Patch Set 7: Commit-Queue+1 (2 comments) Please don’t reply on this GitHub thread. Visit golang.org/cl/555855. |
Message from Go LUCI: Patch Set 7: Dry run: CV is trying the patch. Bot data: {"action":"start","triggered_at":"2024-02-27T23:11:06Z","revision":"0ae37daaddf1821075c94dcfb5658d9e54b88479"} Please don’t reply on this GitHub thread. Visit golang.org/cl/555855. |
Message from Damien Neil: Patch Set 7: -Commit-Queue Please don’t reply on this GitHub thread. Visit golang.org/cl/555855. |
Message from Go LUCI: Patch Set 7: This CL has passed the run Please don’t reply on this GitHub thread. Visit golang.org/cl/555855. |
Message from Go LUCI: Patch Set 7: LUCI-TryBot-Result+1 Please don’t reply on this GitHub thread. Visit golang.org/cl/555855. |
This small PR allows optimizations made in io.Copy (like the use of
io.WriterTo) to be used in one possible path of http.ServeContent
(in case of a non-Range request).
This, in turn, allows us to skip the buffer allocation in io.Copy.
This is a retry of CL446276, reverted to address #61530 (whose root
cause has since been addressed)