mirror of
https://github.com/gogrlx/nats-server.git
synced 2026-04-02 03:38:42 -07:00
Reduce allocations in WebSocket compression
Signed-off-by: Neil Twigg <neil@nats.io>
This commit is contained in:
@@ -346,20 +346,23 @@ func nbPoolGet(sz int) []byte {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func nbPoolPut(b []byte) {
|
func nbPoolPut(in []byte) {
|
||||||
switch cap(b) {
|
ca := cap(in)
|
||||||
case nbPoolSizeSmall:
|
for in = in[:ca]; ca >= nbPoolSizeSmall; ca = cap(in) {
|
||||||
b := (*[nbPoolSizeSmall]byte)(b[0:nbPoolSizeSmall])
|
switch {
|
||||||
nbPoolSmall.Put(b)
|
case ca >= nbPoolSizeLarge:
|
||||||
case nbPoolSizeMedium:
|
b := (*[nbPoolSizeLarge]byte)(in[0:nbPoolSizeLarge:nbPoolSizeLarge])
|
||||||
b := (*[nbPoolSizeMedium]byte)(b[0:nbPoolSizeMedium])
|
nbPoolLarge.Put(b)
|
||||||
nbPoolMedium.Put(b)
|
in = in[nbPoolSizeLarge:]
|
||||||
case nbPoolSizeLarge:
|
case ca >= nbPoolSizeMedium:
|
||||||
b := (*[nbPoolSizeLarge]byte)(b[0:nbPoolSizeLarge])
|
b := (*[nbPoolSizeMedium]byte)(in[0:nbPoolSizeMedium:nbPoolSizeMedium])
|
||||||
nbPoolLarge.Put(b)
|
nbPoolMedium.Put(b)
|
||||||
default:
|
in = in[nbPoolSizeMedium:]
|
||||||
// Ignore frames that are the wrong size, this might happen
|
case ca >= nbPoolSizeSmall:
|
||||||
// with WebSocket/MQTT messages as they are framed
|
b := (*[nbPoolSizeSmall]byte)(in[0:nbPoolSizeSmall:nbPoolSizeSmall])
|
||||||
|
nbPoolSmall.Put(b)
|
||||||
|
in = in[nbPoolSizeSmall:]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -115,6 +115,7 @@ type websocket struct {
|
|||||||
nocompfrag bool // No fragment for compressed frames
|
nocompfrag bool // No fragment for compressed frames
|
||||||
maskread bool
|
maskread bool
|
||||||
maskwrite bool
|
maskwrite bool
|
||||||
|
compressor *flate.Writer
|
||||||
cookieJwt string
|
cookieJwt string
|
||||||
clientIP string
|
clientIP string
|
||||||
}
|
}
|
||||||
@@ -1295,7 +1296,13 @@ func (c *client) wsCollapsePtoNB() (net.Buffers, int64) {
|
|||||||
mfs = 0
|
mfs = 0
|
||||||
}
|
}
|
||||||
buf := bytes.NewBuffer(nbPoolGet(usz))
|
buf := bytes.NewBuffer(nbPoolGet(usz))
|
||||||
cp, _ := flate.NewWriter(buf, flate.BestSpeed)
|
cp := c.ws.compressor
|
||||||
|
if cp == nil {
|
||||||
|
c.ws.compressor, _ = flate.NewWriter(buf, flate.BestSpeed)
|
||||||
|
cp = c.ws.compressor
|
||||||
|
} else {
|
||||||
|
cp.Reset(buf)
|
||||||
|
}
|
||||||
var csz int
|
var csz int
|
||||||
for _, b := range nb {
|
for _, b := range nb {
|
||||||
cp.Write(b)
|
cp.Write(b)
|
||||||
@@ -1323,9 +1330,7 @@ func (c *client) wsCollapsePtoNB() (net.Buffers, int64) {
|
|||||||
if mask {
|
if mask {
|
||||||
wsMaskBuf(key, p[:lp])
|
wsMaskBuf(key, p[:lp])
|
||||||
}
|
}
|
||||||
new := nbPoolGet(wsFrameSizeForBrowsers)
|
bufs = append(bufs, fh[:n], p[:lp])
|
||||||
lp = copy(new[:wsFrameSizeForBrowsers], p[:lp])
|
|
||||||
bufs = append(bufs, fh[:n], new[:lp])
|
|
||||||
csz += n + lp
|
csz += n + lp
|
||||||
p = p[lp:]
|
p = p[lp:]
|
||||||
}
|
}
|
||||||
@@ -1335,16 +1340,9 @@ func (c *client) wsCollapsePtoNB() (net.Buffers, int64) {
|
|||||||
if mask {
|
if mask {
|
||||||
wsMaskBuf(key, p)
|
wsMaskBuf(key, p)
|
||||||
}
|
}
|
||||||
bufs = append(bufs, h)
|
bufs = append(bufs, h, p)
|
||||||
for len(p) > 0 {
|
|
||||||
new := nbPoolGet(len(p))
|
|
||||||
n := copy(new[:cap(new)], p)
|
|
||||||
bufs = append(bufs, new[:n])
|
|
||||||
p = p[n:]
|
|
||||||
}
|
|
||||||
csz = len(h) + ol
|
csz = len(h) + ol
|
||||||
}
|
}
|
||||||
nbPoolPut(b) // No longer needed as we copied from above.
|
|
||||||
// Add to pb the compressed data size (including headers), but
|
// Add to pb the compressed data size (including headers), but
|
||||||
// remove the original uncompressed data size that was added
|
// remove the original uncompressed data size that was added
|
||||||
// during the queueing.
|
// during the queueing.
|
||||||
@@ -1355,14 +1353,15 @@ func (c *client) wsCollapsePtoNB() (net.Buffers, int64) {
|
|||||||
if mfs > 0 {
|
if mfs > 0 {
|
||||||
// We are limiting the frame size.
|
// We are limiting the frame size.
|
||||||
startFrame := func() int {
|
startFrame := func() int {
|
||||||
bufs = append(bufs, nbPoolGet(wsMaxFrameHeaderSize)[:wsMaxFrameHeaderSize])
|
bufs = append(bufs, nbPoolGet(wsMaxFrameHeaderSize))
|
||||||
return len(bufs) - 1
|
return len(bufs) - 1
|
||||||
}
|
}
|
||||||
endFrame := func(idx, size int) {
|
endFrame := func(idx, size int) {
|
||||||
|
bufs[idx] = bufs[idx][:wsMaxFrameHeaderSize]
|
||||||
n, key := wsFillFrameHeader(bufs[idx], mask, wsFirstFrame, wsFinalFrame, wsUncompressedFrame, wsBinaryMessage, size)
|
n, key := wsFillFrameHeader(bufs[idx], mask, wsFirstFrame, wsFinalFrame, wsUncompressedFrame, wsBinaryMessage, size)
|
||||||
|
bufs[idx] = bufs[idx][:n]
|
||||||
c.out.pb += int64(n)
|
c.out.pb += int64(n)
|
||||||
c.ws.fs += int64(n + size)
|
c.ws.fs += int64(n + size)
|
||||||
bufs[idx] = bufs[idx][:n]
|
|
||||||
if mask {
|
if mask {
|
||||||
wsMaskBufs(key, bufs[idx+1:])
|
wsMaskBufs(key, bufs[idx+1:])
|
||||||
}
|
}
|
||||||
@@ -1388,10 +1387,8 @@ func (c *client) wsCollapsePtoNB() (net.Buffers, int64) {
|
|||||||
if endStart {
|
if endStart {
|
||||||
fhIdx = startFrame()
|
fhIdx = startFrame()
|
||||||
}
|
}
|
||||||
new := nbPoolGet(total)
|
bufs = append(bufs, b[:total])
|
||||||
n := copy(new[:cap(new)], b[:total])
|
b = b[total:]
|
||||||
bufs = append(bufs, new[:n])
|
|
||||||
b = b[n:]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if total > 0 {
|
if total > 0 {
|
||||||
|
|||||||
Reference in New Issue
Block a user