Hoist temporary buffers outside the loop.

Otherwise the buffers are re-allocated on every iteration, which is a
surprise to me. I thought the compiler would do this transformation
itself.

Now there is just one allocation per client←server read (one
messageReader) and two allocations per server←client read (one
messageReader and one messageWriter).

	$ go test -bench=BenchmarkReadWrite -benchmem -benchtime=5s
	BenchmarkReadWrite/c←s_150-4              481054             12849 ns/op          11.67 MB/s           8 B/op          1 allocs/op
	BenchmarkReadWrite/s←c_150-4              421809             14095 ns/op          10.64 MB/s          56 B/op          2 allocs/op
	BenchmarkReadWrite/c←s_3000-4             208564             28003 ns/op         107.13 MB/s          16 B/op          2 allocs/op
	BenchmarkReadWrite/s←c_3000-4             186320             30576 ns/op          98.12 MB/s         112 B/op          4 allocs/op
This commit is contained in:
David Fifield 2022-09-22 15:53:04 -06:00
parent 264425a488
commit 2321642f3c

View file

@ -42,6 +42,7 @@ func (conn *Conn) SetDeadline(t time.Time) error {
}
func readLoop(w io.Writer, ws *websocket.Conn) error {
var buf [2048]byte
for {
messageType, r, err := ws.NextReader()
if err != nil {
@ -50,7 +51,6 @@ func readLoop(w io.Writer, ws *websocket.Conn) error {
if messageType != websocket.BinaryMessage && messageType != websocket.TextMessage {
continue
}
var buf [2048]byte
_, err = io.CopyBuffer(w, r, buf[:])
if err != nil {
return err
@ -59,8 +59,8 @@ func readLoop(w io.Writer, ws *websocket.Conn) error {
}
func writeLoop(ws *websocket.Conn, r io.Reader) error {
var buf [2048]byte
for {
var buf [2048]byte
n, err := r.Read(buf[:])
if err != nil {
return err