4
4
"bytes"
5
5
"io"
6
6
"net"
7
+ "sync"
7
8
8
9
"crypto/rand"
9
10
"crypto/rsa"
@@ -15,6 +16,29 @@ import (
15
16
. "github.com/siddontang/go-mysql/mysql"
16
17
)
17
18
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
+
18
42
/*
19
43
Conn is the base class to handle MySQL protocol.
20
44
*/
@@ -24,24 +48,31 @@ type Conn struct {
24
48
// we removed the buffer reader because it will cause the SSLRequest to block (tls connection handshake won't be
25
49
// able to read the "Client Hello" data since it has been buffered into the buffer reader)
26
50
51
+ bufPool * BufPool
52
+
27
53
Sequence uint8
28
54
}
29
55
30
56
func NewConn (conn net.Conn ) * Conn {
31
57
c := new (Conn )
32
58
33
59
c .Conn = conn
60
+ c .bufPool = NewBufPool ()
34
61
35
62
return c
36
63
}
37
64
38
65
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 )
40
69
41
- if err := c .ReadPacketTo (& buf ); err != nil {
70
+ if err := c .ReadPacketTo (buf ); err != nil {
42
71
return nil , errors .Trace (err )
43
72
} else {
44
- return buf .Bytes (), nil
73
+ result := make ([]byte , buf .Len ())
74
+ copy (result , buf .Bytes ())
75
+ return result , nil
45
76
}
46
77
}
47
78
@@ -66,6 +97,11 @@ func (c *Conn) ReadPacketTo(w io.Writer) error {
66
97
67
98
c .Sequence ++
68
99
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
+
69
105
if n , err := io .CopyN (w , c .Conn , int64 (length )); err != nil {
70
106
return ErrBadConn
71
107
} else if n != int64 (length ) {
0 commit comments