Skip to content

Commit a602069

Browse files
committed
Grow buffer instead of using a tmp slice
1 parent de021f9 commit a602069

File tree

1 file changed

+30
-45
lines changed

1 file changed

+30
-45
lines changed

buffer.go

+30-45
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,9 @@
99

1010
package mysql
1111

12-
import (
13-
"io"
14-
)
12+
import "io"
1513

16-
const (
17-
defaultBufSize = 4096
18-
)
14+
const defaultBufSize = 4096
1915

2016
type buffer struct {
2117
buf []byte
@@ -38,6 +34,11 @@ func (b *buffer) fill(need int) (err error) {
3834
copy(b.buf[0:b.length], b.buf[b.idx:])
3935
}
4036

37+
// grow buffer if necessary
38+
if need > len(b.buf) {
39+
b.grow(need)
40+
}
41+
4142
b.idx = 0
4243

4344
var n int
@@ -54,48 +55,32 @@ func (b *buffer) fill(need int) (err error) {
5455
return
5556
}
5657

57-
// returns next N bytes from buffer.
58-
// The returned slice is only guaranteed to be valid until the next read
59-
func (b *buffer) readNext(need int) (p []byte, err error) {
60-
// return slice from buffer if possible
61-
if b.length >= need {
62-
p = b.buf[b.idx : b.idx+need]
63-
b.idx += need
64-
b.length -= need
58+
// credit for this code snippet goes to Maxim Khitrov
59+
// https://groups.google.com/forum/#!topic/golang-nuts/ETbw1ECDgRs
60+
func (b *buffer) grow(size int) {
61+
if size > 2*cap(b.buf) {
62+
newBuf := make([]byte, size)
63+
copy(newBuf, b.buf)
64+
b.buf = newBuf
6565
return
66-
6766
} else {
68-
69-
// does the data fit into the buffer?
70-
if need < len(b.buf) {
71-
// refill
72-
err = b.fill(need) // err deferred
73-
p = b.buf[:need]
74-
b.idx += need
75-
b.length -= need
76-
return
77-
78-
} else {
79-
p = make([]byte, need)
80-
has := 0
81-
82-
// copy data that is already in the buffer
83-
if b.length > 0 {
84-
copy(p[0:b.length], b.buf[b.idx:])
85-
has = b.length
86-
need -= has
87-
b.idx = 0
88-
b.length = 0
89-
}
90-
91-
// read rest directly into the new slice
92-
var n int
93-
for err == nil && need > 0 {
94-
n, err = b.rd.Read(p[has:])
95-
has += n
96-
need -= n
97-
}
67+
for cap(b.buf) < size {
68+
b.buf = append(b.buf[:cap(b.buf)], 0)
9869
}
70+
b.buf = b.buf[:cap(b.buf)]
71+
}
72+
}
73+
74+
// returns next N bytes from buffer.
75+
// The returned slice is only guaranteed to be valid until the next read
76+
func (b *buffer) readNext(need int) (p []byte, err error) {
77+
if b.length < need {
78+
// refill
79+
err = b.fill(need) // err deferred
9980
}
81+
82+
p = b.buf[b.idx : b.idx+need]
83+
b.idx += need
84+
b.length -= need
10085
return
10186
}

0 commit comments

Comments
 (0)