Search code examples
gowebsocketbuffergorilla

Gorilla Websocket WriteMessage leading Out of memory on using WriteBufferPool


I've upgraded to websocket with following upgrader

var upgrader = websocket.Upgrader{
    ReadBufferSize:    1024,
    WriteBufferPool:   &writeBufferPool,
    EnableCompression: false,
}

var writeBufferPool = sync.Pool{
    New: func() interface{} {
        return make([]byte, 1024)
    },
}

On using WriteBufferPool, memory consumption pattern is almost similar as using upgrader without WriteBufferPool.

I came across beginMessage method that initiates buffer as following. Here pool buffer is being typecasted to a private type that isn't exposed to create WriteBufferPool. I suspect if this is leading to buffer remaining unused.

if c.writeBuf == nil {
    wpd, ok := c.writePool.Get().(writePoolData)
    if ok {
        c.writeBuf = wpd.buf
    } else {
        c.writeBuf = make([]byte, c.writeBufSize)
    }
}

For reference, here is the code snippet that listens on a channel and writs to the socket

for data := range clientConnChannel {
    err = ws.WriteMessage(websocket.TextMessage, []byte(data.Raw))
    if err != nil {
        logger.ErrorWithCtx(
            ctx, "unable to write message to client", err,
        )
        break
    }
}

Can you help here if I'm missing something while using WriteBufferPool


Solution

  • The BufferPool documentation says

    The type of the value stored in a pool is not specified.

    Your application incorrectly assumes that the value stored in the pool is specified as []byte.

    Fix your application by removing the sync.Pool's New function.

    var upgrader = websocket.Upgrader{
        ReadBufferSize:    1024,
        WriteBufferPool:   &sync.Pool{},
        EnableCompression: false,
    }