aboutsummaryrefslogtreecommitdiff
path: root/src/bytes/buffer_test.go
diff options
context:
space:
mode:
authorMarvin Stenger <marvin.stenger94@gmail.com>2017-05-07 10:43:17 +0200
committerBrad Fitzpatrick <bradfitz@golang.org>2017-05-07 17:44:46 +0000
commitc08ac36761d3dc03d0a0b0ffb240c4a7c524536b (patch)
treef2af53853e2c5111cf692b6090bafe0e404ae18a /src/bytes/buffer_test.go
parent23c5db9bbbfe2d5656b8f153e1cc7327e90d8005 (diff)
downloadgo-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.go29
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 = '☺'