From 9722e2bd6a800b0953480bc3e2e4da043b5a49dc Mon Sep 17 00:00:00 2001 From: Kevin Pollet Date: Thu, 13 Nov 2025 10:34:09 +0100 Subject: [PATCH] Revert "Avoid allocations in readLoop by using sync.Pool" --- .golangci.yml | 6 ++---- pkg/udp/conn.go | 36 ++++++++---------------------------- 2 files changed, 10 insertions(+), 32 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 949f689dc..50afac812 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -239,6 +239,8 @@ linters: text: ' always receives ' linters: - unparam + - path: pkg/server/service/bufferpool.go + text: 'SA6002: argument should be pointer-like to avoid allocations' - path: pkg/server/middleware/middlewares.go text: Function 'buildConstructor' has too many statements linters: @@ -314,12 +316,8 @@ linters: text: 'the methods of "wasmMiddlewareBuilder" use pointer receiver and non-pointer receiver.' linters: - recvcheck - - path: pkg/server/service/bufferpool.go - text: 'SA6002: argument should be pointer-like to avoid allocations' - path: pkg/proxy/httputil/bufferpool.go text: 'SA6002: argument should be pointer-like to avoid allocations' - - path: pkg/udp/conn.go - text: 'SA6002: argument should be pointer-like to avoid allocations' - path: integration/integration_test.go text: 'var (gatewayAPIConformanceRunTest|traefikVersion) is unused' - path: pkg/server/router/router.go diff --git a/pkg/udp/conn.go b/pkg/udp/conn.go index 2a53b0a6b..36778f648 100644 --- a/pkg/udp/conn.go +++ b/pkg/udp/conn.go @@ -32,9 +32,6 @@ type Listener struct { // timeout defines how long to wait on an idle session, // before releasing its related resources. timeout time.Duration - - // readBufferPool is a pool of byte slices for UDP packet reading. - readBufferPool sync.Pool } // ListenPacketConn creates a new listener from PacketConn. @@ -54,11 +51,6 @@ func ListenPacketConn(packetConn net.PacketConn, timeout time.Duration) (*Listen conns: make(map[string]*Conn), accepting: true, timeout: timeout, - readBufferPool: sync.Pool{ - New: func() interface{} { - return make([]byte, maxDatagramSize) - }, - }, } go l.readLoop() @@ -160,26 +152,21 @@ func (l *Listener) readLoop() { for { // Allocating a new buffer for every read avoids // overwriting data in c.msgs in case the next packet is received - // before c.msgs is emptied via Read(). - // Reuses buffers via the readBufferPool sync.Pool. - buf := l.readBufferPool.Get().([]byte) + // before c.msgs is emptied via Read() + buf := make([]byte, maxDatagramSize) n, raddr, err := l.pConn.ReadFrom(buf) if err != nil { - l.readBufferPool.Put(buf) return } conn, err := l.getConn(raddr) if err != nil { - l.readBufferPool.Put(buf) continue } select { - // Receiver must call releaseReadBuffer() when done reading the data. case conn.receiveCh <- buf[:n]: case <-conn.doneCh: - l.readBufferPool.Put(buf) continue } } @@ -224,15 +211,15 @@ type Conn struct { listener *Listener rAddr net.Addr - receiveCh chan []byte // to receive the data from the listener's readLoop. - readCh chan []byte // to receive the buffer into which we should Read. - sizeCh chan int // to synchronize with the end of a Read. - msgs [][]byte // to store data from listener, to be consumed by Reads. + receiveCh chan []byte // to receive the data from the listener's readLoop + readCh chan []byte // to receive the buffer into which we should Read + sizeCh chan int // to synchronize with the end of a Read + msgs [][]byte // to store data from listener, to be consumed by Reads muActivity sync.RWMutex - lastActivity time.Time // the last time the session saw either read or write activity. + lastActivity time.Time // the last time the session saw either read or write activity - timeout time.Duration // for timeouts. + timeout time.Duration // for timeouts doneOnce sync.Once doneCh chan struct{} } @@ -267,8 +254,6 @@ func (c *Conn) readLoop() { msg := c.msgs[0] c.msgs = c.msgs[1:] n := copy(cBuf, msg) - // Return buffer to sync.Pool once done reading from it. - c.listener.readBufferPool.Put(msg) c.sizeCh <- n case msg := <-c.receiveCh: c.msgs = append(c.msgs, msg) @@ -314,11 +299,6 @@ func (c *Conn) Write(p []byte) (n int, err error) { func (c *Conn) close() { c.doneOnce.Do(func() { - // Release any buffered data before closing. - for _, msg := range c.msgs { - c.listener.readBufferPool.Put(msg) - } - c.msgs = nil close(c.doneCh) }) }