mirror of
https://github.com/zr-hebo/sniffer-agent.git
synced 2025-08-12 00:26:28 +08:00
use cache reduce malloc
This commit is contained in:
66
model/cache_pool.go
Normal file
66
model/cache_pool.go
Normal file
@@ -0,0 +1,66 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"unsafe"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
|
||||
type sliceBufferPool struct {
|
||||
queue chan []byte
|
||||
bufferSize int
|
||||
name string
|
||||
}
|
||||
|
||||
func NewSliceBufferPool(name string, bufferSize int) (sbp *sliceBufferPool) {
|
||||
return &sliceBufferPool{
|
||||
queue: make(chan []byte, 512),
|
||||
bufferSize: bufferSize,
|
||||
name: name,
|
||||
}
|
||||
}
|
||||
|
||||
func (sbp *sliceBufferPool) Enqueue(buffer []byte) {
|
||||
defer func() {
|
||||
log.Debugf("after enqueue from %s, there is %d elements", sbp.name, len(sbp.queue))
|
||||
}()
|
||||
|
||||
if cap(buffer) < 1 {
|
||||
return
|
||||
}
|
||||
|
||||
sbp.queue <- buffer
|
||||
}
|
||||
|
||||
func (sbp *sliceBufferPool) DequeueWithInit(initSize int) (buffer []byte) {
|
||||
if initSize >= sbp.bufferSize {
|
||||
panic(fmt.Sprintf("package size bigger than max buffer size need deal:%d",
|
||||
sbp.bufferSize))
|
||||
}
|
||||
|
||||
defer func() {
|
||||
// reset cache byte
|
||||
pbytes := (*reflect.SliceHeader)(unsafe.Pointer(&buffer))
|
||||
pbytes.Len = initSize
|
||||
}()
|
||||
|
||||
buffer = sbp.Dequeue()
|
||||
return
|
||||
}
|
||||
|
||||
func (sbp *sliceBufferPool) Dequeue() (buffer []byte) {
|
||||
defer func() {
|
||||
log.Debugf("after dequeue from %s, there is %d elements", sbp.name, len(sbp.queue))
|
||||
}()
|
||||
|
||||
select {
|
||||
case buffer = <- sbp.queue:
|
||||
return
|
||||
default:
|
||||
buffer = make([]byte, 0, sbp.bufferSize)
|
||||
return
|
||||
}
|
||||
}
|
@@ -1,14 +1,16 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
// "encoding/json"
|
||||
"github.com/json-iterator/go"
|
||||
"bytes"
|
||||
|
||||
"encoding/json"
|
||||
// "github.com/json-iterator/go"
|
||||
"time"
|
||||
|
||||
"github.com/pingcap/tidb/util/hack"
|
||||
)
|
||||
|
||||
var json = jsoniter.ConfigCompatibleWithStandardLibrary
|
||||
// var json = jsoniter.ConfigCompatibleWithStandardLibrary
|
||||
|
||||
type QueryPiece interface {
|
||||
String() *string
|
||||
@@ -32,20 +34,23 @@ type MysqlQueryPiece struct {
|
||||
ThrowPacketRate float64 `json:"tpr"`
|
||||
BeginTime int64 `json:"bt"`
|
||||
CostTimeInMS int64 `json:"cms"`
|
||||
|
||||
jsonContent []byte `json:"-"`
|
||||
}
|
||||
|
||||
type PooledMysqlQueryPiece struct {
|
||||
MysqlQueryPiece
|
||||
recoverPool *mysqlQueryPiecePool
|
||||
sliceBufferPool *sliceBufferPool
|
||||
}
|
||||
|
||||
const (
|
||||
datetimeFormat = "2006-01-02 15:04:05"
|
||||
millSecondUnit = int64(time.Millisecond)
|
||||
)
|
||||
|
||||
var (
|
||||
mqpp = NewMysqlQueryPiecePool()
|
||||
localSliceBufferPool = NewSliceBufferPool("json cache", 2*1024*1024)
|
||||
)
|
||||
|
||||
func NewPooledMysqlQueryPiece(
|
||||
@@ -53,11 +58,6 @@ func NewPooledMysqlQueryPiece(
|
||||
clientPort, serverPort int, throwPacketRate float64, stmtBeginTime int64) (
|
||||
mqp *PooledMysqlQueryPiece) {
|
||||
mqp = mqpp.Dequeue()
|
||||
if mqp == nil {
|
||||
mqp = &PooledMysqlQueryPiece{
|
||||
MysqlQueryPiece: MysqlQueryPiece{},
|
||||
}
|
||||
}
|
||||
|
||||
nowInMS := time.Now().UnixNano() / millSecondUnit
|
||||
mqp.SessionID = sessionID
|
||||
@@ -73,6 +73,7 @@ func NewPooledMysqlQueryPiece(
|
||||
mqp.BeginTime = stmtBeginTime
|
||||
mqp.CostTimeInMS = nowInMS - stmtBeginTime
|
||||
mqp.recoverPool = mqpp
|
||||
mqp.sliceBufferPool = localSliceBufferPool
|
||||
|
||||
return
|
||||
}
|
||||
@@ -83,13 +84,23 @@ func (mqp *MysqlQueryPiece) String() (*string) {
|
||||
return &contentStr
|
||||
}
|
||||
|
||||
func (mqp *MysqlQueryPiece) Bytes() (bytes []byte) {
|
||||
content, err := json.Marshal(mqp)
|
||||
if err != nil {
|
||||
return []byte(err.Error())
|
||||
func (mqp *MysqlQueryPiece) Bytes() (content []byte) {
|
||||
// content, err := json.Marshal(mqp)
|
||||
if len(mqp.jsonContent) > 0 {
|
||||
return mqp.jsonContent
|
||||
}
|
||||
|
||||
return content
|
||||
var cacheBuffer = localSliceBufferPool.Dequeue()
|
||||
buffer := bytes.NewBuffer(cacheBuffer)
|
||||
err := json.NewEncoder(buffer).Encode(mqp)
|
||||
if err != nil {
|
||||
mqp.jsonContent = []byte(err.Error())
|
||||
|
||||
} else {
|
||||
mqp.jsonContent = buffer.Bytes()
|
||||
}
|
||||
|
||||
return mqp.jsonContent
|
||||
}
|
||||
|
||||
func (mqp *MysqlQueryPiece) GetSQL() (str *string) {
|
||||
@@ -106,4 +117,6 @@ func (mqp *MysqlQueryPiece) SetNeedSyncSend(syncSend bool) {
|
||||
|
||||
func (pmqp *PooledMysqlQueryPiece) Recovery() {
|
||||
pmqp.recoverPool.Enqueue(pmqp)
|
||||
pmqp.sliceBufferPool.Enqueue(pmqp.jsonContent[:0])
|
||||
pmqp.jsonContent = nil
|
||||
}
|
||||
|
@@ -5,13 +5,13 @@ import (
|
||||
)
|
||||
|
||||
type mysqlQueryPiecePool struct {
|
||||
queue []*PooledMysqlQueryPiece
|
||||
queue chan *PooledMysqlQueryPiece
|
||||
lock sync.Mutex
|
||||
}
|
||||
|
||||
func NewMysqlQueryPiecePool() (mqpp *mysqlQueryPiecePool) {
|
||||
return &mysqlQueryPiecePool{
|
||||
queue: make([]*PooledMysqlQueryPiece, 0, 5000),
|
||||
queue: make(chan *PooledMysqlQueryPiece, 1024),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,18 +19,21 @@ func (mqpp *mysqlQueryPiecePool) Enqueue(pmqp *PooledMysqlQueryPiece) {
|
||||
mqpp.lock.Lock()
|
||||
defer mqpp.lock.Unlock()
|
||||
|
||||
mqpp.queue = append(mqpp.queue, pmqp)
|
||||
|
||||
mqpp.queue <- pmqp
|
||||
}
|
||||
|
||||
func (mqpp *mysqlQueryPiecePool) Dequeue() (pmqp *PooledMysqlQueryPiece) {
|
||||
mqpp.lock.Lock()
|
||||
defer mqpp.lock.Unlock()
|
||||
|
||||
if len(mqpp.queue) < 1 {
|
||||
return nil
|
||||
select {
|
||||
case pmqp = <- mqpp.queue:
|
||||
return
|
||||
default:
|
||||
pmqp = &PooledMysqlQueryPiece{
|
||||
MysqlQueryPiece: MysqlQueryPiece{},
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
pmqp = mqpp.queue[0]
|
||||
mqpp.queue = mqpp.queue[1:]
|
||||
return
|
||||
}
|
Reference in New Issue
Block a user