Skip to content

Commit 1dc6383

Browse files
haosdentsiddontang
authored andcommitted
Reduce memory allocation at several palces. (#421)
1 parent f52d30c commit 1dc6383

File tree

2 files changed

+46
-3
lines changed

2 files changed

+46
-3
lines changed

packet/conn.go

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"bytes"
55
"io"
66
"net"
7+
"sync"
78

89
"crypto/rand"
910
"crypto/rsa"
@@ -15,6 +16,29 @@ import (
1516
. "github.com/siddontang/go-mysql/mysql"
1617
)
1718

19+
type BufPool struct {
20+
pool *sync.Pool
21+
}
22+
23+
func NewBufPool() *BufPool {
24+
return &BufPool{
25+
pool: &sync.Pool{
26+
New: func() interface{} {
27+
return new(bytes.Buffer)
28+
},
29+
},
30+
}
31+
}
32+
33+
func (b *BufPool) Get() *bytes.Buffer {
34+
return b.pool.Get().(*bytes.Buffer)
35+
}
36+
37+
func (b *BufPool) Return(buf *bytes.Buffer) {
38+
buf.Reset()
39+
b.pool.Put(buf)
40+
}
41+
1842
/*
1943
Conn is the base class to handle MySQL protocol.
2044
*/
@@ -24,24 +48,31 @@ type Conn struct {
2448
// we removed the buffer reader because it will cause the SSLRequest to block (tls connection handshake won't be
2549
// able to read the "Client Hello" data since it has been buffered into the buffer reader)
2650

51+
bufPool *BufPool
52+
2753
Sequence uint8
2854
}
2955

3056
func NewConn(conn net.Conn) *Conn {
3157
c := new(Conn)
3258

3359
c.Conn = conn
60+
c.bufPool = NewBufPool()
3461

3562
return c
3663
}
3764

3865
func (c *Conn) ReadPacket() ([]byte, error) {
39-
var buf bytes.Buffer
66+
// Here we use `sync.Pool` to avoid allocate/destroy buffers frequently.
67+
buf := c.bufPool.Get()
68+
defer c.bufPool.Return(buf)
4069

41-
if err := c.ReadPacketTo(&buf); err != nil {
70+
if err := c.ReadPacketTo(buf); err != nil {
4271
return nil, errors.Trace(err)
4372
} else {
44-
return buf.Bytes(), nil
73+
result := make([]byte, buf.Len())
74+
copy(result, buf.Bytes())
75+
return result, nil
4576
}
4677
}
4778

@@ -66,6 +97,11 @@ func (c *Conn) ReadPacketTo(w io.Writer) error {
6697

6798
c.Sequence++
6899

100+
if buf, ok := w.(*bytes.Buffer); ok {
101+
// Allocate the buffer with expected length directly instead of call `grow` and migrate data many times.
102+
buf.Grow(length)
103+
}
104+
69105
if n, err := io.CopyN(w, c.Conn, int64(length)); err != nil {
70106
return ErrBadConn
71107
} else if n != int64(length) {

replication/row_event.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,13 @@ func (e *RowsEvent) Decode(data []byte) error {
284284
}
285285
}()
286286

287+
// Pre-allocate memory for rows.
288+
rowsLen := e.ColumnCount
289+
if e.needBitmap2 {
290+
rowsLen += e.ColumnCount
291+
}
292+
e.Rows = make([][]interface{}, 0, rowsLen)
293+
287294
for pos < len(data) {
288295
if n, err = e.decodeRows(data[pos:], e.Table, e.ColumnBitmap1); err != nil {
289296
return errors.Trace(err)

0 commit comments

Comments
 (0)