diff options
author | David Fifield <david@bamsoftware.com> | 2022-09-22 16:43:27 -0600 |
---|---|---|
committer | David Fifield <david@bamsoftware.com> | 2022-11-16 13:48:34 -0700 |
commit | 4ae63eccabb8cdbcb8c1f22a91c3bbf27e87076d (patch) | |
tree | cac7749bceb490b240b39150242dc87f300bcb67 | |
parent | 2321642f3cf6d6371f638126d713e645311994ed (diff) | |
download | snowflake-4ae63eccabb8cdbcb8c1f22a91c3bbf27e87076d.tar.gz snowflake-4ae63eccabb8cdbcb8c1f22a91c3bbf27e87076d.zip |
Benchmark websocket.Conn Upgrade creation.
I had thought to set a buffer size of 2048, half the websocket package
default of 4096. But it turns out when you don't set a buffer size, the
websocket package reuses the HTTP server's read/write buffers, which
empirically already have a size of 2048.
$ go test -bench=BenchmarkUpgradeBufferSize -benchmem -benchtime=5s
BenchmarkUpgradeBufferSize/0-4 25669 234566 ns/op 32604 B/op 113 allocs/op
BenchmarkUpgradeBufferSize/128-4 24739 238283 ns/op 24325 B/op 117 allocs/op
BenchmarkUpgradeBufferSize/1024-4 25352 238885 ns/op 28087 B/op 116 allocs/op
BenchmarkUpgradeBufferSize/2048-4 22660 234890 ns/op 32444 B/op 116 allocs/op
BenchmarkUpgradeBufferSize/4096-4 25668 232591 ns/op 41672 B/op 116 allocs/op
BenchmarkUpgradeBufferSize/8192-4 24908 240755 ns/op 59103 B/op 116 allocs/op
-rw-r--r-- | common/websocketconn/websocketconn_test.go | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/common/websocketconn/websocketconn_test.go b/common/websocketconn/websocketconn_test.go index e7698d1..672d83d 100644 --- a/common/websocketconn/websocketconn_test.go +++ b/common/websocketconn/websocketconn_test.go @@ -264,6 +264,73 @@ func TestClose(t *testing.T) { } } +// Benchmark creating a server websocket.Conn (without the websocketconn.Conn +// wrapper) for different read/write buffer sizes. +func BenchmarkUpgradeBufferSize(b *testing.B) { + // Buffer size of 0 would mean the default of 4096: + // https://github.com/gorilla/websocket/blob/v1.5.0/conn.go#L37 + // But a size of zero also has the effect of causing reuse of the HTTP + // server's buffers. So we test 4096 separately from 0. + // https://github.com/gorilla/websocket/blob/v1.5.0/server.go#L32 + for _, bufSize := range []int{0, 128, 1024, 2048, 4096, 8192} { + upgrader := websocket.Upgrader{ + CheckOrigin: func(*http.Request) bool { return true }, + ReadBufferSize: bufSize, + WriteBufferSize: bufSize, + } + b.Run(fmt.Sprintf("%d", bufSize), func(b *testing.B) { + // Start up a web server to receive the request. + ln, err := net.Listen("tcp", "127.0.0.1:0") + if err != nil { + b.Fatal(err) + } + defer ln.Close() + wsCh := make(chan *websocket.Conn) + errCh := make(chan error) + server := http.Server{ + Handler: http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + ws, err := upgrader.Upgrade(rw, req, nil) + if err != nil { + errCh <- err + return + } + wsCh <- ws + }), + } + defer server.Close() + go func() { + err := server.Serve(ln) + if err != nil && err != http.ErrServerClosed { + errCh <- err + } + }() + + // Make a request to the web server. + dialer := &websocket.Dialer{ + ReadBufferSize: bufSize, + WriteBufferSize: bufSize, + } + urlStr := (&url.URL{Scheme: "ws", Host: ln.Addr().String()}).String() + + b.ResetTimer() + for i := 0; i < b.N; i++ { + ws, _, err := dialer.Dial(urlStr, nil) + if err != nil { + b.Fatal(err) + } + ws.Close() + + select { + case <-wsCh: + case err := <-errCh: + b.Fatal(err) + } + } + b.StopTimer() + }) + } +} + // Benchmark read/write in the client←server and server←client directions, with // messages of different sizes. Run with -benchmem to see memory allocations. func BenchmarkReadWrite(b *testing.B) { |