Commit 1baf35e4 authored by Russ Cox's avatar Russ Cox

bytes: shuffle implementation, making WriteByte 50% faster

R=r
CC=golang-dev
https://golang.org/cl/920041
parent ba1e025f
...@@ -63,54 +63,44 @@ func (b *Buffer) Truncate(n int) { ...@@ -63,54 +63,44 @@ func (b *Buffer) Truncate(n int) {
// b.Reset() is the same as b.Truncate(0). // b.Reset() is the same as b.Truncate(0).
func (b *Buffer) Reset() { b.Truncate(0) } func (b *Buffer) Reset() { b.Truncate(0) }
// Resize buffer to guarantee enough space for n more bytes. // Grow buffer to guarantee space for n more bytes.
// After this call, the state of b.buf is inconsistent. // Return index where bytes should be written.
// It must be fixed up as is done in Write and WriteString. func (b *Buffer) grow(n int) int {
func (b *Buffer) resize(n int) {
var buf []byte
if b.buf == nil && n <= len(b.bootstrap) {
buf = &b.bootstrap
} else {
// not enough space anywhere
buf = make([]byte, 2*cap(b.buf)+n)
copy(buf, b.buf[b.off:])
}
b.buf = buf
b.off = 0
}
// Write appends the contents of p to the buffer. The return
// value n is the length of p; err is always nil.
func (b *Buffer) Write(p []byte) (n int, err os.Error) {
m := b.Len() m := b.Len()
// If buffer is empty, reset to recover space. // If buffer is empty, reset to recover space.
if m == 0 && b.off != 0 { if m == 0 && b.off != 0 {
b.Truncate(0) b.Truncate(0)
} }
n = len(p)
if len(b.buf)+n > cap(b.buf) { if len(b.buf)+n > cap(b.buf) {
b.resize(n) var buf []byte
if b.buf == nil && n <= len(b.bootstrap) {
buf = &b.bootstrap
} else {
// not enough space anywhere
buf = make([]byte, 2*cap(b.buf)+n)
copy(buf, b.buf[b.off:])
}
b.buf = buf
b.off = 0
} }
b.buf = b.buf[0 : b.off+m+n] b.buf = b.buf[0 : b.off+m+n]
copy(b.buf[b.off+m:], p) return b.off + m
return n, nil }
// Write appends the contents of p to the buffer. The return
// value n is the length of p; err is always nil.
func (b *Buffer) Write(p []byte) (n int, err os.Error) {
m := b.grow(len(p))
copy(b.buf[m:], p)
return len(p), nil
} }
// WriteString appends the contents of s to the buffer. The return // WriteString appends the contents of s to the buffer. The return
// value n is the length of s; err is always nil. // value n is the length of s; err is always nil.
func (b *Buffer) WriteString(s string) (n int, err os.Error) { func (b *Buffer) WriteString(s string) (n int, err os.Error) {
m := b.Len() m := b.grow(len(s))
// If buffer is empty, reset to recover space. copyString(b.buf, m, s)
if m == 0 && b.off != 0 { return len(s), nil
b.Truncate(0)
}
n = len(s)
if len(b.buf)+n > cap(b.buf) {
b.resize(n)
}
b.buf = b.buf[0 : b.off+m+n]
copyString(b.buf, b.off+m, s)
return n, nil
} }
// MinRead is the minimum slice size passed to a Read call by // MinRead is the minimum slice size passed to a Read call by
...@@ -177,8 +167,8 @@ func (b *Buffer) WriteTo(w io.Writer) (n int64, err os.Error) { ...@@ -177,8 +167,8 @@ func (b *Buffer) WriteTo(w io.Writer) (n int64, err os.Error) {
// The returned error is always nil, but is included // The returned error is always nil, but is included
// to match bufio.Writer's WriteByte. // to match bufio.Writer's WriteByte.
func (b *Buffer) WriteByte(c byte) os.Error { func (b *Buffer) WriteByte(c byte) os.Error {
b.runeBytes[0] = c m := b.grow(1)
b.Write(b.runeBytes[0:1]) b.buf[m] = c
return nil return nil
} }
......
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