diff options
| author | Damien Neil <dneil@google.com> | 2026-03-12 14:44:28 -0700 |
|---|---|---|
| committer | Gopher Robot <gobot@golang.org> | 2026-03-12 15:28:22 -0700 |
| commit | b3ee07636a1fe4ba5129705fd4692b442cf6b6f0 (patch) | |
| tree | e3c19c06293417689f3561b6275b79cbf72e3f36 /src/net/http | |
| parent | 0dc89195f9aece70476320be3fc9d6d657904056 (diff) | |
| download | go-b3ee07636a1fe4ba5129705fd4692b442cf6b6f0.tar.xz | |
net/http/internal/http2: drop benchmarks which use synctest
Drop a number of low-level benchmarks which use internal test APIs
that now use synctest. Synctest and benchmarks don't really mix;
we don't necessarily expect bubbled code to perform in the same
fashion as unbubbled code.
Fixes #78114
Change-Id: I23f0a5d296ffeabc836f3865e08778eb6a6a6964
Reviewed-on: https://go-review.googlesource.com/c/go/+/754940
Reviewed-by: Nicholas Husin <nsh@golang.org>
Reviewed-by: Nicholas Husin <husin@google.com>
Auto-Submit: Damien Neil <dneil@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Diffstat (limited to 'src/net/http')
| -rw-r--r-- | src/net/http/internal/http2/export_test.go | 4 | ||||
| -rw-r--r-- | src/net/http/internal/http2/server.go | 12 | ||||
| -rw-r--r-- | src/net/http/internal/http2/server_test.go | 313 |
3 files changed, 3 insertions, 326 deletions
diff --git a/src/net/http/internal/http2/export_test.go b/src/net/http/internal/http2/export_test.go index a9e230f5d0..8593ea3628 100644 --- a/src/net/http/internal/http2/export_test.go +++ b/src/net/http/internal/http2/export_test.go @@ -166,10 +166,6 @@ func SummarizeFrame(f Frame) string { return summarizeFrame(f) } -func SetTestHookGetServerConn(t testing.TB, f func(*serverConn)) { - SetForTest(t, &testHookGetServerConn, f) -} - func init() { testHookOnPanicMu = new(sync.Mutex) } diff --git a/src/net/http/internal/http2/server.go b/src/net/http/internal/http2/server.go index a37a7280dd..ebfe16f59a 100644 --- a/src/net/http/internal/http2/server.go +++ b/src/net/http/internal/http2/server.go @@ -82,10 +82,9 @@ var responseWriterStatePool = sync.Pool{ // Test hooks. var ( - testHookOnConn func() - testHookGetServerConn func(*serverConn) - testHookOnPanicMu *sync.Mutex // nil except in tests - testHookOnPanic func(sc *serverConn, panicVal interface{}) (rePanic bool) + testHookOnConn func() + testHookOnPanicMu *sync.Mutex // nil except in tests + testHookOnPanic func(sc *serverConn, panicVal interface{}) (rePanic bool) ) // Server is an HTTP/2 server. @@ -269,7 +268,6 @@ func (s *Server) Configure(conf ServerConfig, tcfg *tls.Config) error { // during next-proto selection, but using TLS <1.2 with // HTTP/2 is still the client's bug. - tcfg.PreferServerCipherSuites = true return nil } @@ -483,10 +481,6 @@ func (s *Server) serveConn(c net.Conn, opts *ServeConnOpts, newf func(*serverCon opts.Settings = nil } - if hook := testHookGetServerConn; hook != nil { - hook(sc) - } - sc.serve(conf) } diff --git a/src/net/http/internal/http2/server_test.go b/src/net/http/internal/http2/server_test.go index 11edfcb3be..d25650e936 100644 --- a/src/net/http/internal/http2/server_test.go +++ b/src/net/http/internal/http2/server_test.go @@ -349,99 +349,6 @@ func (call *serverHandlerCall) exit() { }) } -// newServerTesterWithRealConn creates a test server listening on a localhost port. -// Mostly superseded by newServerTester, which creates a test server using a fake -// net.Conn and synthetic time. This function is still around because some benchmarks -// rely on it; new tests should use newServerTester. -func newServerTesterWithRealConn(t testing.TB, handler http.HandlerFunc, opts ...interface{}) *serverTester { - ts := httptest.NewUnstartedServer(handler) - t.Cleanup(ts.Close) - - tlsConfig := &tls.Config{ - InsecureSkipVerify: true, - NextProtos: []string{NextProtoTLS}, - } - - var framerReuseFrames bool - h2server := new(Server) - for _, opt := range opts { - switch v := opt.(type) { - case func(*tls.Config): - v(tlsConfig) - case func(*httptest.Server): - v(ts) - case func(*http.Server): - v(ts.Config) - case func(*Server): - v(h2server) - case serverTesterOpt: - switch v { - case optFramerReuseFrames: - framerReuseFrames = true - } - case func(net.Conn, http.ConnState): - ts.Config.ConnState = v - default: - t.Fatalf("unknown newServerTester option type %T", v) - } - } - - // Go 1.22 changes the default minimum TLS version to TLS 1.2, - // in order to properly test cases where we want to reject low - // TLS versions, we need to explicitly configure the minimum - // version here. - ts.Config.TLSConfig.MinVersion = tls.VersionTLS10 - - st := &serverTester{ - t: t, - } - st.hpackEnc = hpack.NewEncoder(&st.headerBuf) - - ts.TLS = ts.Config.TLSConfig // the httptest.Server has its own copy of this TLS config - if ts.Config.ErrorLog == nil { - ts.Config.ErrorLog = log.New(io.MultiWriter(stderrv(), twriter{t: t, st: st}, &st.serverLogBuf), "", log.LstdFlags) - } - ts.StartTLS() - - if VerboseLogs { - t.Logf("Running test server at: %s", ts.URL) - } - SetTestHookGetServerConn(t, func(v *ServerConn) { - st.scMu.Lock() - defer st.scMu.Unlock() - st.sc = v - }) - log.SetOutput(io.MultiWriter(stderrv(), twriter{t: t, st: st})) - cc, err := tls.Dial("tcp", ts.Listener.Addr().String(), tlsConfig) - if err != nil { - t.Fatal(err) - } - st.cc = cc - st.testConnFramer = testConnFramer{ - t: t, - fr: NewFramer(st.cc, st.cc), - dec: hpack.NewDecoder(InitialHeaderTableSize, nil), - } - if framerReuseFrames { - st.fr.SetReuseFrames() - } - if !LogFrameReads() && !LogFrameWrites() { - st.fr.TestSetDebugReadLoggerf(func(m string, v ...interface{}) { - m = time.Now().Format("2006-01-02 15:04:05.999999999 ") + strings.TrimPrefix(m, "http2: ") + "\n" - st.frameReadLogMu.Lock() - fmt.Fprintf(&st.frameReadLogBuf, m, v...) - st.frameReadLogMu.Unlock() - }) - st.fr.TestSetDebugWriteLoggerf(func(m string, v ...interface{}) { - m = time.Now().Format("2006-01-02 15:04:05.999999999 ") + strings.TrimPrefix(m, "http2: ") + "\n" - st.frameWriteLogMu.Lock() - fmt.Fprintf(&st.frameWriteLogBuf, m, v...) - st.frameWriteLogMu.Unlock() - }) - } - return st -} - // sync waits for all goroutines to idle. func (st *serverTester) sync() { synctest.Wait() @@ -3164,162 +3071,6 @@ func testServerDoesntWriteInvalidHeaders(t testing.TB) { }) } -func BenchmarkServerGets(b *testing.B) { - DisableGoroutineTracking(b) - b.ReportAllocs() - - const msg = "Hello, world" - st := newServerTesterWithRealConn(b, func(w http.ResponseWriter, r *http.Request) { - io.WriteString(w, msg) - }) - defer st.Close() - st.greet() - - // Give the server quota to reply. (plus it has the 64KB) - if err := st.fr.WriteWindowUpdate(0, uint32(b.N*len(msg))); err != nil { - b.Fatal(err) - } - - for i := 0; i < b.N; i++ { - id := 1 + uint32(i)*2 - st.writeHeaders(HeadersFrameParam{ - StreamID: id, - BlockFragment: st.encodeHeader(), - EndStream: true, - EndHeaders: true, - }) - st.wantFrameType(FrameHeaders) - if df := readFrame[*DataFrame](b, st); !df.StreamEnded() { - b.Fatalf("DATA didn't have END_STREAM; got %v", df) - } - } -} - -func BenchmarkServerPosts(b *testing.B) { - DisableGoroutineTracking(b) - b.ReportAllocs() - - const msg = "Hello, world" - st := newServerTesterWithRealConn(b, func(w http.ResponseWriter, r *http.Request) { - // Consume the (empty) body from th peer before replying, otherwise - // the server will sometimes (depending on scheduling) send the peer a - // a RST_STREAM with the CANCEL error code. - if n, err := io.Copy(io.Discard, r.Body); n != 0 || err != nil { - b.Errorf("Copy error; got %v, %v; want 0, nil", n, err) - } - io.WriteString(w, msg) - }) - defer st.Close() - st.greet() - - // Give the server quota to reply. (plus it has the 64KB) - if err := st.fr.WriteWindowUpdate(0, uint32(b.N*len(msg))); err != nil { - b.Fatal(err) - } - - for i := 0; i < b.N; i++ { - id := 1 + uint32(i)*2 - st.writeHeaders(HeadersFrameParam{ - StreamID: id, - BlockFragment: st.encodeHeader(":method", "POST"), - EndStream: false, - EndHeaders: true, - }) - st.writeData(id, true, nil) - st.wantFrameType(FrameHeaders) - if df := readFrame[*DataFrame](b, st); !df.StreamEnded() { - b.Fatalf("DATA didn't have END_STREAM; got %v", df) - } - } -} - -// Send a stream of messages from server to client in separate data frames. -// Brings up performance issues seen in long streams. -// Created to show problem in go issue #18502 -func BenchmarkServerToClientStreamDefaultOptions(b *testing.B) { - benchmarkServerToClientStream(b) -} - -// Justification for Change-Id: Iad93420ef6c3918f54249d867098f1dadfa324d8 -// Expect to see memory/alloc reduction by opting in to Frame reuse with the Framer. -func BenchmarkServerToClientStreamReuseFrames(b *testing.B) { - benchmarkServerToClientStream(b, optFramerReuseFrames) -} - -func benchmarkServerToClientStream(b *testing.B, newServerOpts ...interface{}) { - DisableGoroutineTracking(b) - b.ReportAllocs() - const msgLen = 1 - // default window size - const windowSize = 1<<16 - 1 - - // next message to send from the server and for the client to expect - nextMsg := func(i int) []byte { - msg := make([]byte, msgLen) - msg[0] = byte(i) - if len(msg) != msgLen { - panic("invalid test setup msg length") - } - return msg - } - - st := newServerTesterWithRealConn(b, func(w http.ResponseWriter, r *http.Request) { - // Consume the (empty) body from th peer before replying, otherwise - // the server will sometimes (depending on scheduling) send the peer a - // a RST_STREAM with the CANCEL error code. - if n, err := io.Copy(io.Discard, r.Body); n != 0 || err != nil { - b.Errorf("Copy error; got %v, %v; want 0, nil", n, err) - } - for i := 0; i < b.N; i += 1 { - w.Write(nextMsg(i)) - w.(http.Flusher).Flush() - } - }, newServerOpts...) - defer st.Close() - st.greet() - - const id = uint32(1) - - st.writeHeaders(HeadersFrameParam{ - StreamID: id, - BlockFragment: st.encodeHeader(":method", "POST"), - EndStream: false, - EndHeaders: true, - }) - - st.writeData(id, true, nil) - st.wantHeaders(wantHeader{ - streamID: 1, - endStream: false, - }) - - var pendingWindowUpdate = uint32(0) - - for i := 0; i < b.N; i += 1 { - expected := nextMsg(i) - st.wantData(wantData{ - streamID: 1, - endStream: false, - data: expected, - }) - // try to send infrequent but large window updates so they don't overwhelm the test - pendingWindowUpdate += uint32(len(expected)) - if pendingWindowUpdate >= windowSize/2 { - if err := st.fr.WriteWindowUpdate(0, pendingWindowUpdate); err != nil { - b.Fatal(err) - } - if err := st.fr.WriteWindowUpdate(id, pendingWindowUpdate); err != nil { - b.Fatal(err) - } - pendingWindowUpdate = 0 - } - } - st.wantData(wantData{ - streamID: 1, - endStream: true, - }) -} - func TestIssue53(t *testing.T) { synctestTest(t, testIssue53) } func testIssue53(t testing.TB) { const data = "PRI * HTTP/2.0\r\n\r\nSM" + @@ -3494,70 +3245,6 @@ func testServerContentLengthCanBeDisabled(t testing.TB) { }) } -func BenchmarkServer_GetRequest(b *testing.B) { - DisableGoroutineTracking(b) - b.ReportAllocs() - const msg = "Hello, world." - st := newServerTesterWithRealConn(b, func(w http.ResponseWriter, r *http.Request) { - n, err := io.Copy(io.Discard, r.Body) - if err != nil || n > 0 { - b.Errorf("Read %d bytes, error %v; want 0 bytes.", n, err) - } - io.WriteString(w, msg) - }) - defer st.Close() - - st.greet() - // Give the server quota to reply. (plus it has the 64KB) - if err := st.fr.WriteWindowUpdate(0, uint32(b.N*len(msg))); err != nil { - b.Fatal(err) - } - hbf := st.encodeHeader(":method", "GET") - for i := 0; i < b.N; i++ { - streamID := uint32(1 + 2*i) - st.writeHeaders(HeadersFrameParam{ - StreamID: streamID, - BlockFragment: hbf, - EndStream: true, - EndHeaders: true, - }) - st.wantFrameType(FrameHeaders) - st.wantFrameType(FrameData) - } -} - -func BenchmarkServer_PostRequest(b *testing.B) { - DisableGoroutineTracking(b) - b.ReportAllocs() - const msg = "Hello, world." - st := newServerTesterWithRealConn(b, func(w http.ResponseWriter, r *http.Request) { - n, err := io.Copy(io.Discard, r.Body) - if err != nil || n > 0 { - b.Errorf("Read %d bytes, error %v; want 0 bytes.", n, err) - } - io.WriteString(w, msg) - }) - defer st.Close() - st.greet() - // Give the server quota to reply. (plus it has the 64KB) - if err := st.fr.WriteWindowUpdate(0, uint32(b.N*len(msg))); err != nil { - b.Fatal(err) - } - hbf := st.encodeHeader(":method", "POST") - for i := 0; i < b.N; i++ { - streamID := uint32(1 + 2*i) - st.writeHeaders(HeadersFrameParam{ - StreamID: streamID, - BlockFragment: hbf, - EndStream: false, - EndHeaders: true, - }) - st.writeData(streamID, true, nil) - st.wantFrameType(FrameHeaders) - st.wantFrameType(FrameData) - } -} - // golang.org/issue/14214 func TestServer_Rejects_ConnHeaders(t *testing.T) { synctestTest(t, testServer_Rejects_ConnHeaders) } func testServer_Rejects_ConnHeaders(t testing.TB) { |
