From f715f173558c13ba445bda7ad527f3cdb6b1351b Mon Sep 17 00:00:00 2001
From: huangjunwei <huangjunwei@youmi.net>
Date: Mon, 26 Feb 2024 00:20:54 +0800
Subject: [PATCH 1/4] tune slice append performance

---
 canal/sync.go                 | 12 ++++++------
 replication/binlogstreamer.go |  4 ++--
 replication/event.go          |  8 ++++----
 replication/parser.go         |  3 +--
 replication/row_event.go      | 24 +++++++++---------------
 5 files changed, 22 insertions(+), 29 deletions(-)

diff --git a/canal/sync.go b/canal/sync.go
index b7006b17e..49cb1b59f 100644
--- a/canal/sync.go
+++ b/canal/sync.go
@@ -183,12 +183,12 @@ type node struct {
 func parseStmt(stmt ast.StmtNode) (ns []*node) {
 	switch t := stmt.(type) {
 	case *ast.RenameTableStmt:
-		for _, tableInfo := range t.TableToTables {
-			n := &node{
+		ns = make([]*node, len(t.TableToTables))
+		for i, tableInfo := range t.TableToTables {
+			ns[i] = &node{
 				db:    tableInfo.OldTable.Schema.String(),
 				table: tableInfo.OldTable.Name.String(),
 			}
-			ns = append(ns, n)
 		}
 	case *ast.AlterTableStmt:
 		n := &node{
@@ -197,12 +197,12 @@ func parseStmt(stmt ast.StmtNode) (ns []*node) {
 		}
 		ns = []*node{n}
 	case *ast.DropTableStmt:
-		for _, table := range t.Tables {
-			n := &node{
+		ns = make([]*node, len(t.Tables))
+		for i, table := range t.Tables {
+			ns[i] = &node{
 				db:    table.Schema.String(),
 				table: table.Name.String(),
 			}
-			ns = append(ns, n)
 		}
 	case *ast.CreateTableStmt:
 		n := &node{
diff --git a/replication/binlogstreamer.go b/replication/binlogstreamer.go
index 72bc7ddd0..276e26722 100644
--- a/replication/binlogstreamer.go
+++ b/replication/binlogstreamer.go
@@ -60,9 +60,9 @@ func (s *BinlogStreamer) GetEventWithStartTime(ctx context.Context, startTime ti
 // DumpEvents dumps all left events
 func (s *BinlogStreamer) DumpEvents() []*BinlogEvent {
 	count := len(s.ch)
-	events := make([]*BinlogEvent, 0, count)
+	events := make([]*BinlogEvent, count)
 	for i := 0; i < count; i++ {
-		events = append(events, <-s.ch)
+		events[i] = <-s.ch
 	}
 	return events
 }
diff --git a/replication/event.go b/replication/event.go
index 566efedaf..07896bec1 100644
--- a/replication/event.go
+++ b/replication/event.go
@@ -225,17 +225,17 @@ type PreviousGTIDsEvent struct {
 }
 
 func (e *PreviousGTIDsEvent) Decode(data []byte) error {
-	var previousGTIDSets []string
 	pos := 0
 	uuidCount := binary.LittleEndian.Uint16(data[pos : pos+8])
 	pos += 8
 
+	previousGTIDSets := make([]string, uuidCount)
 	for i := uint16(0); i < uuidCount; i++ {
 		uuid := e.decodeUuid(data[pos : pos+16])
 		pos += 16
 		sliceCount := binary.LittleEndian.Uint16(data[pos : pos+8])
 		pos += 8
-		var intervals []string
+		intervals := make([]string, sliceCount)
 		for i := uint16(0); i < sliceCount; i++ {
 			start := e.decodeInterval(data[pos : pos+8])
 			pos += 8
@@ -247,9 +247,9 @@ func (e *PreviousGTIDsEvent) Decode(data []byte) error {
 			} else {
 				interval = fmt.Sprintf("%d-%d", start, stop-1)
 			}
-			intervals = append(intervals, interval)
+			intervals[i] = interval
 		}
-		previousGTIDSets = append(previousGTIDSets, fmt.Sprintf("%s:%s", uuid, strings.Join(intervals, ":")))
+		previousGTIDSets[i] = fmt.Sprintf("%s:%s", uuid, strings.Join(intervals, ":"))
 	}
 	e.GTIDSets = strings.Join(previousGTIDSets, ",")
 	return nil
diff --git a/replication/parser.go b/replication/parser.go
index 4caf496c2..514eb8764 100644
--- a/replication/parser.go
+++ b/replication/parser.go
@@ -142,8 +142,7 @@ func (p *BinlogParser) parseSingleEvent(r io.Reader, onEvent OnEventFunc) (bool,
 		return false, errors.Errorf("invalid raw data size in event %s, need %d but got %d", h.EventType, h.EventSize, buf.Len())
 	}
 
-	var rawData []byte
-	rawData = append(rawData, buf.Bytes()...)
+	rawData := buf.Bytes()
 	bodyLen := int(h.EventSize) - EventHeaderSize
 	body := rawData[EventHeaderSize:]
 	if len(body) != bodyLen {
diff --git a/replication/row_event.go b/replication/row_event.go
index 5828f8b77..a0d42e8ec 100644
--- a/replication/row_event.go
+++ b/replication/row_event.go
@@ -570,12 +570,9 @@ func (e *TableMapEvent) SetStrValueString() [][]string {
 		if len(e.SetStrValue) == 0 {
 			return nil
 		}
-		e.setStrValueString = make([][]string, 0, len(e.SetStrValue))
-		for _, vals := range e.SetStrValue {
-			e.setStrValueString = append(
-				e.setStrValueString,
-				e.bytesSlice2StrSlice(vals),
-			)
+		e.setStrValueString = make([][]string, len(e.SetStrValue))
+		for i, vals := range e.SetStrValue {
+			e.setStrValueString[i] = e.bytesSlice2StrSlice(vals)
 		}
 	}
 	return e.setStrValueString
@@ -588,12 +585,9 @@ func (e *TableMapEvent) EnumStrValueString() [][]string {
 		if len(e.EnumStrValue) == 0 {
 			return nil
 		}
-		e.enumStrValueString = make([][]string, 0, len(e.EnumStrValue))
-		for _, vals := range e.EnumStrValue {
-			e.enumStrValueString = append(
-				e.enumStrValueString,
-				e.bytesSlice2StrSlice(vals),
-			)
+		e.enumStrValueString = make([][]string, len(e.EnumStrValue))
+		for i, vals := range e.EnumStrValue {
+			e.enumStrValueString[i] = e.bytesSlice2StrSlice(vals)
 		}
 	}
 	return e.enumStrValueString
@@ -612,9 +606,9 @@ func (e *TableMapEvent) bytesSlice2StrSlice(src [][]byte) []string {
 	if src == nil {
 		return nil
 	}
-	ret := make([]string, 0, len(src))
-	for _, item := range src {
-		ret = append(ret, string(item))
+	ret := make([]string, len(src))
+	for i, item := range src {
+		ret[i] = string(item)
 	}
 	return ret
 }

From 7e2158e0b5b22958d3fa2717d979f51fb392d07a Mon Sep 17 00:00:00 2001
From: huangjunwei <huangjunwei@youmi.net>
Date: Fri, 1 Mar 2024 23:36:36 +0800
Subject: [PATCH 2/4] revert

---
 replication/parser.go | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/replication/parser.go b/replication/parser.go
index 514eb8764..4caf496c2 100644
--- a/replication/parser.go
+++ b/replication/parser.go
@@ -142,7 +142,8 @@ func (p *BinlogParser) parseSingleEvent(r io.Reader, onEvent OnEventFunc) (bool,
 		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 {

From 6b06040b4d606c2f3b38d94eeecefa0450729003 Mon Sep 17 00:00:00 2001
From: huangjunwei <huangjunwei@youmi.net>
Date: Sat, 2 Mar 2024 00:03:19 +0800
Subject: [PATCH 3/4] tune raw data slice assignment

---
 replication/parser.go | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/replication/parser.go b/replication/parser.go
index 4caf496c2..7e3a9370f 100644
--- a/replication/parser.go
+++ b/replication/parser.go
@@ -142,8 +142,10 @@ func (p *BinlogParser) parseSingleEvent(r io.Reader, onEvent OnEventFunc) (bool,
 		return false, errors.Errorf("invalid raw data size in event %s, need %d but got %d", h.EventType, h.EventSize, buf.Len())
 	}
 
-	var rawData []byte
-	rawData = append(rawData, buf.Bytes()...)
+	rawData := make([]byte, buf.Len())
+	for i, b := range buf.Bytes() {
+		rawData[i] = b
+	}
 	bodyLen := int(h.EventSize) - EventHeaderSize
 	body := rawData[EventHeaderSize:]
 	if len(body) != bodyLen {

From 848265ed3ce18d13f77fc1208d29c1aa79f41c83 Mon Sep 17 00:00:00 2001
From: huangjunwei <huangjunwei@youmi.net>
Date: Mon, 4 Mar 2024 21:42:58 +0800
Subject: [PATCH 4/4] commit as suggested

---
 replication/binlogstreamer.go | 2 +-
 replication/event.go          | 4 ++--
 replication/parser.go         | 6 ++----
 3 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/replication/binlogstreamer.go b/replication/binlogstreamer.go
index 276e26722..5214e92dd 100644
--- a/replication/binlogstreamer.go
+++ b/replication/binlogstreamer.go
@@ -61,7 +61,7 @@ func (s *BinlogStreamer) GetEventWithStartTime(ctx context.Context, startTime ti
 func (s *BinlogStreamer) DumpEvents() []*BinlogEvent {
 	count := len(s.ch)
 	events := make([]*BinlogEvent, count)
-	for i := 0; i < count; i++ {
+	for i := range events {
 		events[i] = <-s.ch
 	}
 	return events
diff --git a/replication/event.go b/replication/event.go
index 07896bec1..b9e13bf1a 100644
--- a/replication/event.go
+++ b/replication/event.go
@@ -230,13 +230,13 @@ func (e *PreviousGTIDsEvent) Decode(data []byte) error {
 	pos += 8
 
 	previousGTIDSets := make([]string, uuidCount)
-	for i := uint16(0); i < uuidCount; i++ {
+	for i := range previousGTIDSets {
 		uuid := e.decodeUuid(data[pos : pos+16])
 		pos += 16
 		sliceCount := binary.LittleEndian.Uint16(data[pos : pos+8])
 		pos += 8
 		intervals := make([]string, sliceCount)
-		for i := uint16(0); i < sliceCount; i++ {
+		for i := range intervals {
 			start := e.decodeInterval(data[pos : pos+8])
 			pos += 8
 			stop := e.decodeInterval(data[pos : pos+8])
diff --git a/replication/parser.go b/replication/parser.go
index 7e3a9370f..4caf496c2 100644
--- a/replication/parser.go
+++ b/replication/parser.go
@@ -142,10 +142,8 @@ func (p *BinlogParser) parseSingleEvent(r io.Reader, onEvent OnEventFunc) (bool,
 		return false, errors.Errorf("invalid raw data size in event %s, need %d but got %d", h.EventType, h.EventSize, buf.Len())
 	}
 
-	rawData := make([]byte, buf.Len())
-	for i, b := range buf.Bytes() {
-		rawData[i] = b
-	}
+	var rawData []byte
+	rawData = append(rawData, buf.Bytes()...)
 	bodyLen := int(h.EventSize) - EventHeaderSize
 	body := rawData[EventHeaderSize:]
 	if len(body) != bodyLen {