diff --git a/client/conn.go b/client/conn.go index 928e1dfd1..f82b3c465 100644 --- a/client/conn.go +++ b/client/conn.go @@ -5,6 +5,7 @@ import ( "context" "crypto/tls" "fmt" + "math/bits" "net" "runtime" "runtime/debug" @@ -557,13 +558,10 @@ func (c *Conn) execSend(query string) error { // separated by "|". Examples of capability names are CLIENT_DEPRECATE_EOF and CLIENT_PROTOCOL_41. // These are defined as constants in the mysql package. func (c *Conn) CapabilityString() string { - var caps []string capability := c.capability - for i := 0; capability != 0; i++ { - field := uint32(1 << i) - if capability&field == 0 { - continue - } + caps := make([]string, 0, bits.OnesCount32(capability)) + for capability != 0 { + field := uint32(1 << bits.TrailingZeros32(capability)) capability ^= field switch field { @@ -642,13 +640,10 @@ func (c *Conn) CapabilityString() string { // StatusString returns a "|" separated list of status fields. Example status values are SERVER_QUERY_WAS_SLOW and SERVER_STATUS_AUTOCOMMIT. // These are defined as constants in the mysql package. func (c *Conn) StatusString() string { - var stats []string status := c.status - for i := 0; status != 0; i++ { - field := uint16(1 << i) - if status&field == 0 { - continue - } + stats := make([]string, 0, bits.OnesCount16(status)) + for status != 0 { + field := uint16(1 << bits.TrailingZeros16(status)) status ^= field switch field { diff --git a/replication/row_event.go b/replication/row_event.go index d1fe9afa8..d64bfdef2 100644 --- a/replication/row_event.go +++ b/replication/row_event.go @@ -5,6 +5,7 @@ import ( "encoding/hex" "fmt" "io" + "math/bits" "strconv" "strings" "time" @@ -754,7 +755,7 @@ func (e *TableMapEvent) VisibilityMap() map[int]bool { if len(e.VisibilityBitmap) == 0 { return nil } - ret := make(map[int]bool) + ret := make(map[int]bool, len(e.VisibilityBitmap)*8) i := 0 for _, field := range e.VisibilityBitmap { for c := 0x80; c != 0; c >>= 1 { @@ -1146,15 +1147,17 @@ func (e *RowsEvent) decodeImage(data []byte, bitmap []byte, rowImageType EnumRow } row := make([]interface{}, e.ColumnCount) - skips := make([]int, 0) // refer: https://github.com/alibaba/canal/blob/c3e38e50e269adafdd38a48c63a1740cde304c67/dbsync/src/main/java/com/taobao/tddl/dbsync/binlog/event/RowsLogBuffer.java#L63 count := 0 - for i := 0; i < int(e.ColumnCount); i++ { - if isBitSet(bitmap, i) { - count++ - } + col := 0 + for ; col+8 <= int(e.ColumnCount); col += 8 { + count += bits.OnesCount8(bitmap[col>>3]) + } + if col < int(e.ColumnCount) { + count += bits.OnesCount8(bitmap[col>>3] & byte((1<<(int(e.ColumnCount)-col))-1)) } + skips := make([]int, 0, int(e.ColumnCount)-count) count = bitmapByteSize(count) nullBitmap := data[pos : pos+count]