derp: use AvailableBuffer for WriteFrameHeader, consolidate tests (#19101)

Use bufio.Writer.AvailableBuffer to write the frame header directly
into bufio's internal buffer as a single append+Write, avoiding 5
separate WriteByte calls. Fall back to the existing writeUint32
byte-at-a-time path when the buffer has insufficient space.

```
name                  old ns/op  new ns/op  speedup
WriteFrameHeader-8    18.8       7.8        ~2.4x
(0 allocs/op in both)
```

Add TestWriteFrameHeader with correctness
checks, allocation assertions, and coverage of both fast and slow
write paths. Move BenchmarkReadFrameHeader from client_test.go to
derp_test.go alongside BenchmarkWriteFrameHeader, co-located with
the functions under test.

Updates tailscale/corp#38509

Signed-off-by: Mike O'Driscoll <mikeo@tailscale.com>
This commit is contained in:
Mike O'Driscoll
2026-03-24 18:08:01 -04:00
committed by GitHub
parent 9992b7c817
commit f52c1e3615
3 changed files with 119 additions and 33 deletions
-28
View File
@@ -6,7 +6,6 @@ package derp
import (
"bufio"
"bytes"
"io"
"net"
"reflect"
"sync"
@@ -126,33 +125,6 @@ func TestClientSendPong(t *testing.T) {
}
}
func BenchmarkWriteUint32(b *testing.B) {
w := bufio.NewWriter(io.Discard)
b.ReportAllocs()
b.ResetTimer()
for range b.N {
writeUint32(w, 0x0ba3a)
}
}
type nopRead struct{}
func (r nopRead) Read(p []byte) (int, error) {
return len(p), nil
}
func BenchmarkReadFrameHeader(b *testing.B) {
r := bufio.NewReader(nopRead{})
b.ReportAllocs()
b.ResetTimer()
for range b.N {
_, _, err := ReadFrameHeader(r)
if err != nil {
b.Fatal(err)
}
}
}
type countWriter struct {
mu sync.Mutex
writes int