diff options
author | Fazlul Shahriar <fshahriar@gmail.com> | 2020-08-11 16:41:38 -0700 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2020-08-11 16:43:23 -0700 |
commit | 49947d2eb9506d85ec735d17d00060d59997c452 (patch) | |
tree | 88b96420714fac4107247f7140c7e5de438f4a14 /pkg | |
parent | 89f3197fc368702cbe1842932d9cfbede250269f (diff) |
Eliminate one allocation per send/recv for non-flipcall transport.
Ported from https://github.com/hugelgupf/p9/pull/44.
name old time/op new time/op delta
SendRecvLegacy-6 61.5µs ± 6% 60.1µs ±11% ~ (p=0.063 n=9+9)
SendRecv-6 40.7µs ± 2% 39.8µs ± 5% -2.27% (p=0.035 n=10+10)
name old alloc/op new alloc/op delta
SendRecvLegacy-6 769B ± 0% 705B ± 0% -8.37% (p=0.000 n=8+10)
SendRecv-6 320B ± 0% 256B ± 0% -20.00% (p=0.000 n=10+10)
name old allocs/op new allocs/op delta
SendRecvLegacy-6 25.0 ± 0% 23.0 ± 0% -8.00% (p=0.000 n=10+10)
SendRecv-6 14.0 ± 0% 12.0 ± 0% -14.29% (p=0.000 n=10+10)
PiperOrigin-RevId: 326127979
Diffstat (limited to 'pkg')
-rw-r--r-- | pkg/p9/client_test.go | 2 | ||||
-rw-r--r-- | pkg/p9/transport.go | 64 | ||||
-rw-r--r-- | pkg/p9/transport_test.go | 2 |
3 files changed, 33 insertions, 35 deletions
diff --git a/pkg/p9/client_test.go b/pkg/p9/client_test.go index c757583e0..b78fdab7a 100644 --- a/pkg/p9/client_test.go +++ b/pkg/p9/client_test.go @@ -62,6 +62,8 @@ func TestVersion(t *testing.T) { } func benchmarkSendRecv(b *testing.B, fn func(c *Client) func(message, message) error) { + b.ReportAllocs() + // See above. serverSocket, clientSocket, err := unet.SocketPair(false) if err != nil { diff --git a/pkg/p9/transport.go b/pkg/p9/transport.go index 7cec0e86d..02e665345 100644 --- a/pkg/p9/transport.go +++ b/pkg/p9/transport.go @@ -66,14 +66,17 @@ const ( var dataPool = sync.Pool{ New: func() interface{} { // These buffers are used for decoding without a payload. - return make([]byte, initialBufferLength) + // We need to return a pointer to avoid unnecessary allocations + // (see https://staticcheck.io/docs/checks#SA6002). + b := make([]byte, initialBufferLength) + return &b }, } // send sends the given message over the socket. func send(s *unet.Socket, tag Tag, m message) error { - data := dataPool.Get().([]byte) - dataBuf := buffer{data: data[:0]} + data := dataPool.Get().(*[]byte) + dataBuf := buffer{data: (*data)[:0]} if log.IsLogging(log.Debug) { log.Debugf("send [FD %d] [Tag %06d] %s", s.FD(), tag, m.String()) @@ -141,7 +144,7 @@ func send(s *unet.Socket, tag Tag, m message) error { } // All set. - dataPool.Put(dataBuf.data) + dataPool.Put(&dataBuf.data) return nil } @@ -227,12 +230,29 @@ func recv(s *unet.Socket, msize uint32, lookup lookupTagAndType) (Tag, message, // Not yet initialized. var dataBuf buffer + var vecs [][]byte + + appendBuffer := func(size int) *[]byte { + // Pull a data buffer from the pool. + datap := dataPool.Get().(*[]byte) + data := *datap + if size > len(data) { + // Create a larger data buffer. + data = make([]byte, size) + datap = &data + } else { + // Limit the data buffer. + data = data[:size] + } + dataBuf = buffer{data: data} + vecs = append(vecs, data) + return datap + } // Read the rest of the payload. // // This requires some special care to ensure that the vectors all line // up the way they should. We do this to minimize copying data around. - var vecs [][]byte if payloader, ok := m.(payloader); ok { fixedSize := payloader.FixedSize() @@ -246,22 +266,8 @@ func recv(s *unet.Socket, msize uint32, lookup lookupTagAndType) (Tag, message, } if fixedSize != 0 { - // Pull a data buffer from the pool. - data := dataPool.Get().([]byte) - if int(fixedSize) > len(data) { - // Create a larger data buffer, ensuring - // sufficient capicity for the message. - data = make([]byte, fixedSize) - defer dataPool.Put(data) - dataBuf = buffer{data: data} - vecs = append(vecs, data) - } else { - // Limit the data buffer, and make sure it - // gets filled before the payload buffer. - defer dataPool.Put(data) - dataBuf = buffer{data: data[:fixedSize]} - vecs = append(vecs, data[:fixedSize]) - } + datap := appendBuffer(int(fixedSize)) + defer dataPool.Put(datap) } // Include the payload. @@ -274,20 +280,8 @@ func recv(s *unet.Socket, msize uint32, lookup lookupTagAndType) (Tag, message, vecs = append(vecs, p) } } else if remaining != 0 { - // Pull a data buffer from the pool. - data := dataPool.Get().([]byte) - if int(remaining) > len(data) { - // Create a larger data buffer. - data = make([]byte, remaining) - defer dataPool.Put(data) - dataBuf = buffer{data: data} - vecs = append(vecs, data) - } else { - // Limit the data buffer. - defer dataPool.Put(data) - dataBuf = buffer{data: data[:remaining]} - vecs = append(vecs, data[:remaining]) - } + datap := appendBuffer(int(remaining)) + defer dataPool.Put(datap) } if len(vecs) > 0 { diff --git a/pkg/p9/transport_test.go b/pkg/p9/transport_test.go index 3668fcad7..e7406b374 100644 --- a/pkg/p9/transport_test.go +++ b/pkg/p9/transport_test.go @@ -182,6 +182,8 @@ func TestSendClosed(t *testing.T) { } func BenchmarkSendRecv(b *testing.B) { + b.ReportAllocs() + server, client, err := unet.SocketPair(false) if err != nil { b.Fatalf("socketpair got err %v expected nil", err) |