diff --git a/replication/parser.go b/replication/parser.go index 5d8c32eec..7688fe7b0 100644 --- a/replication/parser.go +++ b/replication/parser.go @@ -11,6 +11,8 @@ import ( "time" "github.com/pingcap/errors" + + "github.com/go-mysql-org/go-mysql/utils" ) var ( @@ -110,8 +112,11 @@ func (p *BinlogParser) parseSingleEvent(r io.Reader, onEvent OnEventFunc) (bool, var err error var n int64 - var buf bytes.Buffer - if n, err = io.CopyN(&buf, r, EventHeaderSize); err == io.EOF { + // Here we use `sync.Pool` to avoid allocate/destroy buffers frequently. + buf := utils.BytesBufferGet() + defer utils.BytesBufferPut(buf) + + if n, err = io.CopyN(buf, r, EventHeaderSize); err == io.EOF { return true, nil } else if err != nil { return false, errors.Errorf("get event header err %v, need %d but got %d", err, EventHeaderSize, n) @@ -126,14 +131,15 @@ func (p *BinlogParser) parseSingleEvent(r io.Reader, onEvent OnEventFunc) (bool, if h.EventSize < uint32(EventHeaderSize) { return false, errors.Errorf("invalid event header, event size is %d, too small", h.EventSize) } - if n, err = io.CopyN(&buf, r, int64(h.EventSize-EventHeaderSize)); err != nil { + if n, err = io.CopyN(buf, r, int64(h.EventSize-EventHeaderSize)); err != nil { return false, errors.Errorf("get event err %v, need %d but got %d", err, h.EventSize, n) } if buf.Len() != int(h.EventSize) { return false, errors.Errorf("invalid raw data size in event %s, need %d but got %d", h.EventType, h.EventSize, buf.Len()) } - rawData := buf.Bytes() + var rawData []byte + rawData = append(rawData, buf.Bytes()...) bodyLen := int(h.EventSize) - EventHeaderSize body := rawData[EventHeaderSize:] if len(body) != bodyLen {