From 312bfc5d55994aaef5910716e096a675aa3bce39 Mon Sep 17 00:00:00 2001 From: Chris Marchesi Date: Wed, 6 Mar 2019 03:44:48 +0000 Subject: [PATCH] net/http: add request file upload benchmarks This adds benchmarks to test file uploads using PUT requests. It's designed to complement changes https://golang.org/cl/163599 and https://golang.org/cl/163737, allowing an easy comparison of performance before and after these changes are applied. Updates #30377. Co-authored-by: Emmanuel Odeke Change-Id: Ib8e692c61e1f7957d88c7101669d4f7fb8110c65 GitHub-Last-Rev: 242622b4fca9f289defa2f268efc31208743e5dd GitHub-Pull-Request: golang/go#30424 Reviewed-on: https://go-review.googlesource.com/c/go/+/163862 Run-TryBot: Emmanuel Odeke Reviewed-by: Emmanuel Odeke --- src/net/http/request_test.go | 91 ++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/src/net/http/request_test.go b/src/net/http/request_test.go index e8005571df..4e826fad15 100644 --- a/src/net/http/request_test.go +++ b/src/net/http/request_test.go @@ -8,12 +8,14 @@ import ( "bufio" "bytes" "context" + "crypto/rand" "encoding/base64" "fmt" "io" "io/ioutil" "mime/multipart" . "net/http" + "net/http/httptest" "net/url" "os" "reflect" @@ -1046,3 +1048,92 @@ func BenchmarkReadRequestWrk(b *testing.B) { Host: localhost:8080 `) } + +const ( + withTLS = true + noTLS = false +) + +func BenchmarkFileAndServer_1KB(b *testing.B) { + benchmarkFileAndServer(b, 1<<10) +} + +func BenchmarkFileAndServer_16MB(b *testing.B) { + benchmarkFileAndServer(b, 1<<24) +} + +func BenchmarkFileAndServer_64MB(b *testing.B) { + benchmarkFileAndServer(b, 1<<26) +} + +func benchmarkFileAndServer(b *testing.B, n int64) { + f, err := ioutil.TempFile(os.TempDir(), "go-bench-http-file-and-server") + if err != nil { + b.Fatalf("Failed to create temp file: %v", err) + } + + defer func() { + f.Close() + os.RemoveAll(f.Name()) + }() + + if _, err := io.CopyN(f, rand.Reader, n); err != nil { + b.Fatalf("Failed to copy %d bytes: %v", n, err) + } + + b.Run("NoTLS", func(b *testing.B) { + runFileAndServerBenchmarks(b, noTLS, f, n) + }) + + b.Run("TLS", func(b *testing.B) { + runFileAndServerBenchmarks(b, withTLS, f, n) + }) +} + +func runFileAndServerBenchmarks(b *testing.B, tlsOption bool, f *os.File, n int64) { + handler := HandlerFunc(func(rw ResponseWriter, req *Request) { + defer req.Body.Close() + nc, err := io.Copy(ioutil.Discard, req.Body) + if err != nil { + panic(err) + } + + if nc != n { + panic(fmt.Errorf("Copied %d Wanted %d bytes", nc, n)) + } + }) + + var cst *httptest.Server + if tlsOption == withTLS { + cst = httptest.NewTLSServer(handler) + } else { + cst = httptest.NewServer(handler) + } + + defer cst.Close() + b.ResetTimer() + for i := 0; i < b.N; i++ { + // Perform some setup. + b.StopTimer() + if _, err := f.Seek(0, 0); err != nil { + b.Fatalf("Failed to seek back to file: %v", err) + } + + b.StartTimer() + req, err := NewRequest("PUT", cst.URL, ioutil.NopCloser(f)) + if err != nil { + b.Fatal(err) + } + + req.ContentLength = n + // Prevent mime sniffing by setting the Content-Type. + req.Header.Set("Content-Type", "application/octet-stream") + res, err := cst.Client().Do(req) + if err != nil { + b.Fatalf("Failed to make request to backend: %v", err) + } + + res.Body.Close() + b.SetBytes(n) + } +} -- 2.48.1