Optimize packWithCompression
This commit is contained in:
@ -8,7 +8,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
const MaxDataLength = 2097152
|
const MaxDataLength = 0x200000
|
||||||
|
|
||||||
// Packet define a net data package
|
// Packet define a net data package
|
||||||
type Packet struct {
|
type Packet struct {
|
||||||
@ -37,11 +37,10 @@ func (p Packet) Scan(fields ...FieldDecoder) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var bufPool = sync.Pool{
|
var (
|
||||||
New: func() any {
|
bufPool = sync.Pool{New: func() any { return new(bytes.Buffer) }}
|
||||||
return new(bytes.Buffer)
|
zlibPool = sync.Pool{New: func() any { return zlib.NewWriter(io.Discard) }}
|
||||||
},
|
)
|
||||||
}
|
|
||||||
|
|
||||||
// Pack 打包一个数据包
|
// Pack 打包一个数据包
|
||||||
func (p *Packet) Pack(w io.Writer, threshold int) error {
|
func (p *Packet) Pack(w io.Writer, threshold int) error {
|
||||||
@ -55,63 +54,65 @@ func (p *Packet) Pack(w io.Writer, threshold int) error {
|
|||||||
func (p *Packet) packWithoutCompression(w io.Writer) error {
|
func (p *Packet) packWithoutCompression(w io.Writer) error {
|
||||||
buffer := bufPool.Get().(*bytes.Buffer)
|
buffer := bufPool.Get().(*bytes.Buffer)
|
||||||
defer bufPool.Put(buffer)
|
defer bufPool.Put(buffer)
|
||||||
|
|
||||||
// Pre-allocate room at the front of the packet for the length field
|
|
||||||
buffer.Reset()
|
buffer.Reset()
|
||||||
buffer.Write([]byte{0, 0, 0})
|
|
||||||
|
|
||||||
VarInt(p.ID).WriteTo(buffer)
|
// Write Length to buffer
|
||||||
|
Length := VarInt(VarInt(p.ID).Len() + len(p.Data))
|
||||||
|
_, _ = Length.WriteTo(buffer)
|
||||||
|
|
||||||
|
// Write ID and Data to buffer
|
||||||
|
_, _ = VarInt(p.ID).WriteTo(buffer)
|
||||||
buffer.Write(p.Data)
|
buffer.Write(p.Data)
|
||||||
|
|
||||||
// Write length at front
|
// Write buffer to w
|
||||||
payloadLen := VarInt(buffer.Len() - 3)
|
_, err := w.Write(buffer.Bytes())
|
||||||
varIntOffset := 3 - payloadLen.Len()
|
|
||||||
payloadLen.WriteToBytes(buffer.Bytes()[varIntOffset:])
|
|
||||||
|
|
||||||
_, err := w.Write(buffer.Bytes()[varIntOffset:])
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Packet) packWithCompression(w io.Writer, threshold int) error {
|
func (p *Packet) packWithCompression(w io.Writer, threshold int) error {
|
||||||
buff := bufPool.Get().(*bytes.Buffer)
|
buff := bufPool.Get().(*bytes.Buffer)
|
||||||
defer bufPool.Put(buff)
|
defer bufPool.Put(buff)
|
||||||
// Allocate room for the 'packet length' and 'data length' fields. Each can take up to 3 bytes
|
|
||||||
buff.Reset()
|
buff.Reset()
|
||||||
buff.Write([]byte{0, 0, 0, 0, 0, 0})
|
|
||||||
|
|
||||||
var writeStart int
|
|
||||||
|
|
||||||
|
PacketID := VarInt(p.ID)
|
||||||
if len(p.Data) < threshold {
|
if len(p.Data) < threshold {
|
||||||
VarInt(p.ID).WriteTo(buff)
|
DataLength := VarInt(0) // uncompressed mark
|
||||||
buff.Write(p.Data)
|
PacketLength := VarInt(DataLength.Len() + PacketID.Len() + len(p.Data))
|
||||||
// Packet is below compression threshold so 'data length' is 0
|
_, _ = PacketLength.WriteTo(buff)
|
||||||
// Front of the packet is already initialized to 0, so just decrement the offset
|
_, _ = DataLength.WriteTo(buff)
|
||||||
writeStart = 5
|
_, _ = PacketID.WriteTo(buff)
|
||||||
|
_, _ = buff.Write(p.Data)
|
||||||
} else {
|
} else {
|
||||||
zw := zlib.NewWriter(buff)
|
DataLength := VarInt(PacketID.Len() + len(p.Data))
|
||||||
varIntLen, _ := VarInt(p.ID).WriteTo(zw)
|
|
||||||
zw.Write(p.Data)
|
|
||||||
|
|
||||||
err := zw.Close()
|
buff.Write(make([]byte, MaxVarIntLen)) // padding for Packet Length
|
||||||
if err != nil {
|
_, _ = DataLength.WriteTo(buff)
|
||||||
|
if err := compressPacket(buff, p.ID, p.Data); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write 'data length' before ID + payload
|
PacketLength := VarInt(buff.Len() - MaxVarIntLen)
|
||||||
uncompressedLen := VarInt(varIntLen + int64(len(p.Data)))
|
packetLengthLen := PacketLength.Len()
|
||||||
writeStart = 6 - uncompressedLen.Len()
|
buff.Next(MaxVarIntLen - packetLengthLen)
|
||||||
uncompressedLen.WriteToBytes(buff.Bytes()[writeStart:])
|
PacketLength.WriteToBytes(buff.Bytes()[:packetLengthLen])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write 'packet length' before all other fields
|
_, err := w.Write(buff.Bytes())
|
||||||
packetLen := VarInt(buff.Len() - writeStart)
|
|
||||||
start := writeStart - packetLen.Len()
|
|
||||||
VarInt(packetLen).WriteToBytes(buff.Bytes()[start:])
|
|
||||||
|
|
||||||
_, err := w.Write(buff.Bytes()[start:])
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func compressPacket(w io.Writer, PacketID int32, Data []byte) error {
|
||||||
|
zw := zlibPool.Get().(*zlib.Writer)
|
||||||
|
defer zlibPool.Put(zw)
|
||||||
|
zw.Reset(w)
|
||||||
|
|
||||||
|
_, _ = VarInt(PacketID).WriteTo(zw)
|
||||||
|
if _, err := zw.Write(Data); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return zw.Close()
|
||||||
|
}
|
||||||
|
|
||||||
// UnPack in-place decompression a packet
|
// UnPack in-place decompression a packet
|
||||||
func (p *Packet) UnPack(r io.Reader, threshold int) error {
|
func (p *Packet) UnPack(r io.Reader, threshold int) error {
|
||||||
if threshold >= 0 {
|
if threshold >= 0 {
|
||||||
|
Reference in New Issue
Block a user