diff options
| author | Marvin Stenger <marvin.stenger94@gmail.com> | 2017-05-07 10:43:17 +0200 |
|---|---|---|
| committer | Brad Fitzpatrick <bradfitz@golang.org> | 2017-05-07 17:44:46 +0000 |
| commit | c08ac36761d3dc03d0a0b0ffb240c4a7c524536b (patch) | |
| tree | f2af53853e2c5111cf692b6090bafe0e404ae18a /src/bytes/buffer_test.go | |
| parent | 23c5db9bbbfe2d5656b8f153e1cc7327e90d8005 (diff) | |
| download | go-c08ac36761d3dc03d0a0b0ffb240c4a7c524536b.tar.xz | |
bytes: optimize Buffer's Write, WriteString, WriteByte, and WriteRune
In the common case, the grow method only needs to reslice the internal
buffer. Making another function call to grow can be expensive when Write
is called very often with small pieces of data (like a byte or rune).
Thus, we add a tryGrowByReslice method that is inlineable so that we can
avoid an extra call in most cases.
name old time/op new time/op delta
WriteByte-4 35.5µs ± 0% 17.4µs ± 1% -51.03% (p=0.000 n=19+20)
WriteRune-4 55.7µs ± 1% 38.7µs ± 1% -30.56% (p=0.000 n=18+19)
BufferNotEmptyWriteRead-4 304µs ± 5% 283µs ± 3% -6.86% (p=0.000 n=19+17)
BufferFullSmallReads-4 87.0µs ± 5% 66.8µs ± 2% -23.26% (p=0.000 n=17+17)
name old speed new speed delta
WriteByte-4 115MB/s ± 0% 235MB/s ± 1% +104.19% (p=0.000 n=19+20)
WriteRune-4 221MB/s ± 1% 318MB/s ± 1% +44.01% (p=0.000 n=18+19)
Fixes #17857
Change-Id: I08dfb10a1c7e001817729dbfcc951bda12fe8814
Reviewed-on: https://go-review.googlesource.com/42813
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Diffstat (limited to 'src/bytes/buffer_test.go')
| -rw-r--r-- | src/bytes/buffer_test.go | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/src/bytes/buffer_test.go b/src/bytes/buffer_test.go index a07f58ee44..3c73d7dd86 100644 --- a/src/bytes/buffer_test.go +++ b/src/bytes/buffer_test.go @@ -6,8 +6,10 @@ package bytes_test import ( . "bytes" + "internal/testenv" "io" "math/rand" + "os/exec" "runtime" "testing" "unicode/utf8" @@ -546,6 +548,33 @@ func TestBufferGrowth(t *testing.T) { } } +// Test that tryGrowByReslice is inlined. +func TestTryGrowByResliceInlined(t *testing.T) { + t.Parallel() + goBin := testenv.GoToolPath(t) + out, err := exec.Command(goBin, "tool", "nm", goBin).CombinedOutput() + if err != nil { + t.Fatalf("go tool nm: %v: %s", err, out) + } + // Verify this doesn't exist: + sym := "bytes.(*Buffer).tryGrowByReslice" + if Contains(out, []byte(sym)) { + t.Errorf("found symbol %q in cmd/go, but should be inlined", sym) + } +} + +func BenchmarkWriteByte(b *testing.B) { + const n = 4 << 10 + b.SetBytes(n) + buf := NewBuffer(make([]byte, n)) + for i := 0; i < b.N; i++ { + buf.Reset() + for i := 0; i < n; i++ { + buf.WriteByte('x') + } + } +} + func BenchmarkWriteRune(b *testing.B) { const n = 4 << 10 const r = '☺' |
