Commit 2321895f authored by Martin Möhrmann's avatar Martin Möhrmann Committed by Brad Fitzpatrick

bytes: improve WriteRune performance

Remove the runeBytes buffer and write the utf8 encoding directly
to the internal buf byte slice.

name         old time/op   new time/op   delta
WriteRune-4   80.5µs ± 2%   57.1µs ± 2%  -29.06%  (p=0.000 n=20+20)

name         old speed     new speed     delta
WriteRune-4  153MB/s ± 2%  215MB/s ± 2%  +40.96%  (p=0.000 n=20+20)

Change-Id: Ic15f6e2d6e56a3d15c74f56159e2eae020ba73ba
Reviewed-on: https://go-review.googlesource.com/28816Reviewed-by: 's avatarBrad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent 07bcc165
......@@ -15,11 +15,10 @@ import (
// A Buffer is a variable-sized buffer of bytes with Read and Write methods.
// The zero value for Buffer is an empty buffer ready to use.
type Buffer struct {
buf []byte // contents are the bytes buf[off : len(buf)]
off int // read at &buf[off], write at &buf[len(buf)]
runeBytes [utf8.UTFMax]byte // avoid allocation of slice on each call to WriteRune
bootstrap [64]byte // memory to hold first slice; helps small buffers avoid allocation.
lastRead readOp // last read operation, so that Unread* can work correctly.
buf []byte // contents are the bytes buf[off : len(buf)]
off int // read at &buf[off], write at &buf[len(buf)]
bootstrap [64]byte // memory to hold first slice; helps small buffers avoid allocation.
lastRead readOp // last read operation, so that Unread* can work correctly.
}
// The readOp constants describe the last action performed on
......@@ -246,8 +245,10 @@ func (b *Buffer) WriteRune(r rune) (n int, err error) {
b.WriteByte(byte(r))
return 1, nil
}
n = utf8.EncodeRune(b.runeBytes[0:], r)
b.Write(b.runeBytes[0:n])
b.lastRead = opInvalid
m := b.grow(utf8.UTFMax)
n = utf8.EncodeRune(b.buf[m:m+utf8.UTFMax], r)
b.buf = b.buf[:m+n]
return n, nil
}
......
......@@ -514,6 +514,19 @@ func TestBufferGrowth(t *testing.T) {
}
}
func BenchmarkWriteRune(b *testing.B) {
const n = 4 << 10
const r = '☺'
b.SetBytes(int64(n * utf8.RuneLen(r)))
buf := NewBuffer(make([]byte, n*utf8.UTFMax))
for i := 0; i < b.N; i++ {
buf.Reset()
for i := 0; i < n; i++ {
buf.WriteRune(r)
}
}
}
// From Issue 5154.
func BenchmarkBufferNotEmptyWriteRead(b *testing.B) {
buf := make([]byte, 1024)
......
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