@@ -51,14 +51,14 @@ func (p *packet) readFrom(r *readBuffer) {
51
51
return
52
52
}
53
53
54
- p .data = append ([] byte ( nil ) , data ... ) // TODO: reduce allocations
54
+ p .data = append (p . data [: 0 ] , data ... )
55
55
}
56
56
57
57
// Read packet to buffer 'data'
58
- func (mc * mysqlConn ) readPacket (ctx context.Context ) ([] byte , error ) {
59
- var prevData [] byte
58
+ func (mc * mysqlConn ) readPacket (ctx context.Context ) (* packet , error ) {
59
+ var prevData * packet
60
60
for {
61
- var pkt packet
61
+ var pkt * packet
62
62
select {
63
63
case pkt = <- mc .readRes :
64
64
case <- mc .closech :
@@ -99,12 +99,24 @@ func (mc *mysqlConn) readPacket(ctx context.Context) ([]byte, error) {
99
99
return prevData , nil
100
100
}
101
101
102
- prevData = append (prevData , pkt .data ... )
103
-
104
102
// return data if this was the last packet
105
103
if pktLen < maxPacketSize {
104
+ // zero allocations for non-split packets
105
+ if prevData == nil {
106
+ return pkt , nil
107
+ }
108
+
109
+ prevData .data = append (prevData .data , pkt .data ... )
110
+ mc .connector .putPacket (pkt )
106
111
return prevData , nil
107
112
}
113
+
114
+ if prevData != nil {
115
+ prevData .data = append (prevData .data , pkt .data ... )
116
+ mc .connector .putPacket (pkt )
117
+ } else {
118
+ prevData = pkt
119
+ }
108
120
}
109
121
}
110
122
@@ -209,7 +221,7 @@ func (mc *mysqlConn) writePacket(ctx context.Context, data []byte) error {
209
221
// Handshake Initialization Packet
210
222
// http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::Handshake
211
223
func (mc * mysqlConn ) readHandshakePacket (ctx context.Context ) (data []byte , plugin string , err error ) {
212
- data , err = mc .readPacket (ctx )
224
+ packet , err : = mc .readPacket (ctx )
213
225
if err != nil {
214
226
// for init we can rewrite this to ErrBadConn for sql.Driver to retry, since
215
227
// in connection initialization we don't risk retrying non-idempotent actions.
@@ -218,6 +230,8 @@ func (mc *mysqlConn) readHandshakePacket(ctx context.Context) (data []byte, plug
218
230
}
219
231
return
220
232
}
233
+ defer mc .connector .putPacket (packet )
234
+ data = packet .data
221
235
222
236
if data [0 ] == iERR {
223
237
return nil , "" , mc .handleErrorPacket (data )
@@ -504,10 +518,11 @@ func (mc *mysqlConn) writeCommandPacketUint32(ctx context.Context, command byte,
504
518
******************************************************************************/
505
519
506
520
func (mc * mysqlConn ) readAuthResult (ctx context.Context ) ([]byte , string , error ) {
507
- data , err := mc .readPacket (ctx )
521
+ packet , err := mc .readPacket (ctx )
508
522
if err != nil {
509
523
return nil , "" , err
510
524
}
525
+ data := packet .data
511
526
512
527
// packet indicator
513
528
switch data [0 ] {
@@ -540,10 +555,11 @@ func (mc *mysqlConn) readAuthResult(ctx context.Context) ([]byte, string, error)
540
555
541
556
// Returns error if Packet is not a 'Result OK'-Packet
542
557
func (mc * okHandler ) readResultOK (ctx context.Context ) error {
543
- data , err := mc .conn ().readPacket (ctx )
558
+ packet , err := mc .conn ().readPacket (ctx )
544
559
if err != nil {
545
560
return err
546
561
}
562
+ data := packet .data
547
563
548
564
if data [0 ] == iOK {
549
565
return mc .handleOkPacket (data )
@@ -558,10 +574,12 @@ func (mc *okHandler) readResultSetHeaderPacket(ctx context.Context) (int, error)
558
574
mc .result .affectedRows = append (mc .result .affectedRows , 0 )
559
575
mc .result .insertIds = append (mc .result .insertIds , 0 )
560
576
561
- data , err := mc .conn ().readPacket (ctx )
577
+ packet , err := mc .conn ().readPacket (ctx )
562
578
if err != nil {
563
579
return 0 , err
564
580
}
581
+ defer mc .conn ().connector .putPacket (packet )
582
+ data := packet .data
565
583
if err == nil {
566
584
switch data [0 ] {
567
585
@@ -704,10 +722,11 @@ func (mc *mysqlConn) readColumns(ctx context.Context, count int) ([]mysqlField,
704
722
columns := make ([]mysqlField , count )
705
723
706
724
for i := 0 ; ; i ++ {
707
- data , err := mc .readPacket (ctx )
725
+ packet , err := mc .readPacket (ctx )
708
726
if err != nil {
709
727
return nil , err
710
728
}
729
+ data := packet .data
711
730
712
731
// EOF Packet
713
732
if data [0 ] == iEOF && (len (data ) == 5 || len (data ) == 1 ) {
@@ -808,10 +827,13 @@ func (rows *textRows) readRow(dest []driver.Value) error {
808
827
return io .EOF
809
828
}
810
829
811
- data , err := mc .readPacket (ctx )
830
+ rows .mc .connector .putPacket (rows .pkt )
831
+ packet , err := mc .readPacket (ctx )
832
+ rows .pkt = packet
812
833
if err != nil {
813
834
return err
814
835
}
836
+ data := packet .data
815
837
816
838
// EOF Packet
817
839
if data [0 ] == iEOF && len (data ) == 5 {
@@ -893,10 +915,11 @@ func (rows *textRows) readRow(dest []driver.Value) error {
893
915
// Reads Packets until EOF-Packet or an Error appears. Returns count of Packets read
894
916
func (mc * mysqlConn ) readUntilEOF (ctx context.Context ) error {
895
917
for {
896
- data , err := mc .readPacket (ctx )
918
+ packet , err := mc .readPacket (ctx )
897
919
if err != nil {
898
920
return err
899
921
}
922
+ data := packet .data
900
923
901
924
switch data [0 ] {
902
925
case iERR :
@@ -907,6 +930,7 @@ func (mc *mysqlConn) readUntilEOF(ctx context.Context) error {
907
930
}
908
931
return nil
909
932
}
933
+ mc .connector .putPacket (packet )
910
934
}
911
935
}
912
936
@@ -917,10 +941,12 @@ func (mc *mysqlConn) readUntilEOF(ctx context.Context) error {
917
941
// Prepare Result Packets
918
942
// http://dev.mysql.com/doc/internals/en/com-stmt-prepare-response.html
919
943
func (stmt * mysqlStmt ) readPrepareResultPacket (ctx context.Context ) (uint16 , error ) {
920
- data , err := stmt .mc .readPacket (ctx )
944
+ packet , err := stmt .mc .readPacket (ctx )
921
945
if err != nil {
922
946
return 0 , err
923
947
}
948
+ defer stmt .mc .connector .putPacket (packet )
949
+ data := packet .data
924
950
if err == nil {
925
951
// packet indicator [1 byte]
926
952
if data [0 ] != iOK {
@@ -1253,10 +1279,14 @@ func (mc *okHandler) discardResults(ctx context.Context) error {
1253
1279
// http://dev.mysql.com/doc/internals/en/binary-protocol-resultset-row.html
1254
1280
func (rows * binaryRows ) readRow (dest []driver.Value ) error {
1255
1281
ctx := rows .ctx
1256
- data , err := rows .mc .readPacket (ctx )
1282
+
1283
+ rows .mc .connector .putPacket (rows .pkt )
1284
+ packet , err := rows .mc .readPacket (ctx )
1285
+ rows .pkt = packet
1257
1286
if err != nil {
1258
1287
return err
1259
1288
}
1289
+ data := packet .data
1260
1290
1261
1291
// packet indicator [1 byte]
1262
1292
if data [0 ] != iOK {
@@ -1432,7 +1462,7 @@ func (rows *binaryRows) readRow(dest []driver.Value) error {
1432
1462
1433
1463
func (mc * mysqlConn ) startGoroutines () {
1434
1464
mc .closech = make (chan struct {})
1435
- mc .readRes = make (chan packet )
1465
+ mc .readRes = make (chan * packet )
1436
1466
mc .writeReq = make (chan []byte , 1 )
1437
1467
mc .writeRes = make (chan writeResult )
1438
1468
@@ -1442,7 +1472,7 @@ func (mc *mysqlConn) startGoroutines() {
1442
1472
1443
1473
func (mc * mysqlConn ) readLoop () {
1444
1474
for {
1445
- var pkt packet
1475
+ pkt := mc . connector . getPacket ()
1446
1476
mc .muRead .Lock ()
1447
1477
pkt .readFrom (& mc .rbuf )
1448
1478
mc .muRead .Unlock ()
0 commit comments