Skip to content

Commit 73c990b

Browse files
committed
doc + micro optimization
Optimizations: - one cmp less in loops (-> do while) - optimized loops for branch prediction
1 parent 3b51eea commit 73c990b

File tree

1 file changed

+13
-8
lines changed

1 file changed

+13
-8
lines changed

buffer.go

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import "io"
1313

1414
const defaultBufSize = 4096
1515

16+
// A read buffer similar to bufio.Reader but zero-copy-ish
17+
// Also highly optimized for this particular use case.
1618
type buffer struct {
1719
buf []byte
1820
rd io.Reader
@@ -42,35 +44,38 @@ func (b *buffer) fill(need int) (err error) {
4244
b.idx = 0
4345

4446
var n int
45-
for b.length < need {
47+
for {
4648
n, err = b.rd.Read(b.buf[b.length:])
4749
b.length += n
4850

49-
if err == nil {
51+
if b.length < need && err == nil {
5052
continue
5153
}
5254
return // err
5355
}
54-
55-
return
5656
}
5757

5858
// grow the buffer to at least the given size
5959
// credit for this code snippet goes to Maxim Khitrov
6060
// https://groups.google.com/forum/#!topic/golang-nuts/ETbw1ECDgRs
6161
func (b *buffer) grow(size int) {
6262
// If append would be too expensive, alloc a new slice
63-
if size > 2*cap(b.buf) {
63+
if size > cap(b.buf)*2 {
6464
newBuf := make([]byte, size)
6565
copy(newBuf, b.buf)
6666
b.buf = newBuf
6767
return
6868
}
6969

70-
for cap(b.buf) < size {
71-
b.buf = append(b.buf[:cap(b.buf)], 0)
70+
for {
71+
b.buf = append(b.buf, 0)
72+
b.buf = b.buf[:cap(b.buf)]
73+
74+
if cap(b.buf) < size {
75+
continue
76+
}
77+
return
7278
}
73-
b.buf = b.buf[:cap(b.buf)]
7479
}
7580

7681
// returns next N bytes from buffer.

0 commit comments

Comments
 (0)