derp: remove two key.Public allocations
Reading and writing a [32]byte key to a bufio.Reader/bufio.Writer can easily by done without allocating. Do so. It is slower; on my machine, it adds about 100ns per read/write. However, the overall request takes a minimum of several µs, and it cuts allocations meaningfully, so it is probably worth it. name old time/op new time/op delta SendRecv/msgsize=10-8 9.21µs ± 9% 9.08µs ± 8% ~ (p=0.250 n=15+15) SendRecv/msgsize=100-8 6.51µs ± 9% 6.60µs ± 7% ~ (p=0.259 n=15+13) SendRecv/msgsize=1000-8 7.24µs ±13% 7.61µs ±36% ~ (p=1.000 n=11+15) SendRecv/msgsize=10000-8 19.5µs ±15% 19.9µs ±25% ~ (p=0.890 n=14+15) name old speed new speed delta SendRecv/msgsize=10-8 1.09MB/s ± 8% 1.10MB/s ± 8% ~ (p=0.286 n=15+15) SendRecv/msgsize=100-8 15.4MB/s ± 8% 15.1MB/s ± 6% ~ (p=0.129 n=15+12) SendRecv/msgsize=1000-8 139MB/s ±15% 135MB/s ±28% ~ (p=1.000 n=11+15) SendRecv/msgsize=10000-8 516MB/s ±17% 506MB/s ±21% ~ (p=0.880 n=14+15) name old alloc/op new alloc/op delta SendRecv/msgsize=10-8 170B ± 1% 108B ± 1% -36.63% (p=0.000 n=15+15) SendRecv/msgsize=100-8 265B ± 1% 203B ± 1% -23.34% (p=0.000 n=15+15) SendRecv/msgsize=1000-8 1.18kB ± 1% 1.12kB ± 0% -5.31% (p=0.000 n=14+14) SendRecv/msgsize=10000-8 18.8kB ± 2% 18.8kB ± 2% ~ (p=0.443 n=12+12) name old allocs/op new allocs/op delta SendRecv/msgsize=10-8 4.00 ± 0% 2.00 ± 0% -50.00% (p=0.000 n=15+15) SendRecv/msgsize=100-8 4.00 ± 0% 2.00 ± 0% -50.00% (p=0.000 n=15+15) SendRecv/msgsize=1000-8 4.00 ± 0% 2.00 ± 0% -50.00% (p=0.000 n=15+15) SendRecv/msgsize=10000-8 5.00 ± 0% 3.00 ± 0% -40.00% (p=0.000 n=13+14) Signed-off-by: Josh Bleecher Snyder <josharian@gmail.com>reviewable/pr681/r1
parent
b983e5340f
commit
909c165382
|
@ -746,7 +746,7 @@ func (s *Server) recvPacket(br *bufio.Reader, frameLen uint32) (dstKey key.Publi
|
|||
if frameLen < keyLen {
|
||||
return zpub, nil, errors.New("short send packet frame")
|
||||
}
|
||||
if _, err := io.ReadFull(br, dstKey[:]); err != nil {
|
||||
if err := readPublicKey(br, &dstKey); err != nil {
|
||||
return zpub, nil, err
|
||||
}
|
||||
packetLen := frameLen - keyLen
|
||||
|
@ -1053,7 +1053,8 @@ func (c *sclient) sendPacket(srcKey key.Public, contents []byte) (err error) {
|
|||
return err
|
||||
}
|
||||
if withKey {
|
||||
if _, err = c.bw.Write(srcKey[:]); err != nil {
|
||||
err := writePublicKey(c.bw, &srcKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -1250,3 +1251,34 @@ func (s *Server) ConsistencyCheck() error {
|
|||
}
|
||||
return errors.New(strings.Join(errs, ", "))
|
||||
}
|
||||
|
||||
// readPublicKey reads key from br.
|
||||
// It is ~4x slower than io.ReadFull(br, key),
|
||||
// but it prevents key from escaping and thus being allocated.
|
||||
// If io.ReadFull(br, key) does not cause key to escape, use that instead.
|
||||
func readPublicKey(br *bufio.Reader, key *key.Public) error {
|
||||
// Do io.ReadFull(br, key), but one byte at a time, to avoid allocation.
|
||||
for i := range key {
|
||||
b, err := br.ReadByte()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
key[i] = b
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// writePublicKey writes key to bw.
|
||||
// It is ~3x slower than bw.Write(key[:]),
|
||||
// but it prevents key from escaping and thus being allocated.
|
||||
// If bw.Write(key[:]) does not cause key to escape, use that instead.
|
||||
func writePublicKey(bw *bufio.Writer, key *key.Public) error {
|
||||
// Do bw.Write(key[:]), but one byte at a time to avoid allocation.
|
||||
for _, b := range key {
|
||||
err := bw.WriteByte(b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue