diff options
author | David Fifield <david@bamsoftware.com> | 2022-09-22 15:43:59 -0600 |
---|---|---|
committer | David Fifield <david@bamsoftware.com> | 2022-11-16 13:48:34 -0700 |
commit | 3df514ae2961166088902dbd329b929983b6e002 (patch) | |
tree | a9fdf5e1d3633b6ec5565f4e5735508145166f5e | |
parent | 8cadcaee704053aedb42964ae143ef1597364020 (diff) | |
download | snowflake-3df514ae2961166088902dbd329b929983b6e002.tar.gz snowflake-3df514ae2961166088902dbd329b929983b6e002.zip |
Call WriteMessage directly in websocketconn.Conn.Write.
In the client←server direction, this hits a fast path that avoids
allocating a messageWriter.
https://github.com/gorilla/websocket/blob/v1.5.0/conn.go#L760
Cuts the number of allocations in half in the client←server direction:
$ go test -bench=BenchmarkReadWrite -benchmem -benchtime=5s
BenchmarkReadWrite/c←s_150-4 597511 13358 ns/op 11.23 MB/s 33709 B/op 2 allocs/op
BenchmarkReadWrite/s←c_150-4 474176 13756 ns/op 10.90 MB/s 34968 B/op 4 allocs/op
BenchmarkReadWrite/c←s_3000-4 156488 36290 ns/op 82.67 MB/s 68673 B/op 5 allocs/op
BenchmarkReadWrite/s←c_3000-4 190897 34719 ns/op 86.41 MB/s 69730 B/op 8 allocs/op
-rw-r--r-- | common/websocketconn/websocketconn.go | 19 |
1 files changed, 5 insertions, 14 deletions
diff --git a/common/websocketconn/websocketconn.go b/common/websocketconn/websocketconn.go index c745522..72ac463 100644 --- a/common/websocketconn/websocketconn.go +++ b/common/websocketconn/websocketconn.go @@ -64,16 +64,7 @@ func writeLoop(ws *websocket.Conn, r io.Reader) error { if err != nil { return err } - data := buf[:n] - w, err := ws.NextWriter(websocket.BinaryMessage) - if err != nil { - return err - } - n, err = w.Write(data) - if err != nil { - return err - } - err = w.Close() + err = ws.WriteMessage(websocket.BinaryMessage, buf[:n]) if err != nil { return err } @@ -100,10 +91,10 @@ func New(ws *websocket.Conn) *Conn { // https://godoc.org/github.com/gorilla/websocket#hdr-Concurrency // "Connections support one concurrent reader and one concurrent writer. // Applications are responsible for ensuring that no more than one - // goroutine calls the write methods (NextWriter, etc.) concurrently and - // that no more than one goroutine calls the read methods (NextReader, - // etc.) concurrently. The Close and WriteControl methods can be called - // concurrently with all other methods." + // goroutine calls the write methods (WriteMessage, etc.) concurrently + // and that no more than one goroutine calls the read methods + // (NextReader, etc.) concurrently. The Close and WriteControl methods + // can be called concurrently with all other methods." pr1, pw1 := io.Pipe() go func() { pw1.CloseWithError(closeErrorToEOF(readLoop(pw1, ws))) |