Commit 994f5966 authored by Brad Fitzpatrick's avatar Brad Fitzpatrick

bytes: don't grow Buffer if capacity is available

Also added a new benchmark from the same test:

benchmark                           old ns/op    new ns/op    delta
BenchmarkBufferNotEmptyWriteRead      2643698       709189  -73.17%

Fixes #5154

R=golang-dev, r, gri
CC=golang-dev
https://golang.org/cl/8164043
parent fb3ed166
......@@ -87,6 +87,11 @@ func (b *Buffer) grow(n int) int {
var buf []byte
if b.buf == nil && n <= len(b.bootstrap) {
buf = b.bootstrap[0:]
} else if m+n <= cap(b.buf) {
// We can slide things down instead of
// allocating a new slice.
copy(b.buf[:], b.buf[b.off:])
buf = b.buf[:m]
} else {
// not enough space anywhere
buf = makeSlice(2*cap(b.buf) + n)
......
......@@ -475,3 +475,35 @@ func TestUnreadByte(t *testing.T) {
t.Errorf("ReadByte = %q; want %q", c, 'm')
}
}
// Tests that we occasionally compact. Issue 5154.
func TestBufferGrowth(t *testing.T) {
var b Buffer
buf := make([]byte, 1024)
b.Write(buf[0:1])
var cap0 int
for i := 0; i < 5<<10; i++ {
b.Write(buf)
b.Read(buf)
if i == 0 {
cap0 = b.Cap()
}
}
cap1 := b.Cap()
if cap1 > cap0 {
t.Errorf("buffer cap = %d; too big", cap1)
}
}
// From Issue 5154.
func BenchmarkBufferNotEmptyWriteRead(b *testing.B) {
buf := make([]byte, 1024)
for i := 0; i < b.N; i++ {
var b Buffer
b.Write(buf[0:1])
for i := 0; i < 5<<10; i++ {
b.Write(buf)
b.Read(buf)
}
}
}
......@@ -7,3 +7,7 @@ package bytes
// Export func for testing
var IndexBytePortable = indexBytePortable
var EqualPortable = equalPortable
func (b *Buffer) Cap() int {
return cap(b.buf)
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment