]> Cypherpunks repositories - gostls13.git/commitdiff
bytes: don't grow Buffer if capacity is available
authorBrad Fitzpatrick <bradfitz@golang.org>
Fri, 29 Mar 2013 19:39:19 +0000 (12:39 -0700)
committerBrad Fitzpatrick <bradfitz@golang.org>
Fri, 29 Mar 2013 19:39:19 +0000 (12:39 -0700)
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

src/pkg/bytes/buffer.go
src/pkg/bytes/buffer_test.go
src/pkg/bytes/export_test.go

index 85c1577985d574543f940f8a690b0dd1669cb2df..0328f4c2d8d42aac886ccb1b19d499b735ed580f 100644 (file)
@@ -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)
index f9fb2625a0f39f1fbfe1df0728eeeb451657cc7b..d629809b576abeef98e4e5ac8bb5f32cc81e3f95 100644 (file)
@@ -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)
+               }
+       }
+}
index f61523e60bbb3fd209594912ebcaa76cde9acd20..3b915d5ead80ae1aa7a4e32cb744709f7bd02401 100644 (file)
@@ -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)
+}