1
0
mirror of https://github.com/redis/go-redis.git synced 2025-08-06 01:35:48 +03:00
Files
go-redis/internal/pool/buffer_size_test.go
ofekshenawa 1eed165f9d feat(proto): add configurable buffer sizes for Redis connections (#3453)
* add configurable buffer sizes for Redis connections

* add MiB to wordlist

* Add description for buffer size parameter
2025-08-04 09:16:54 +03:00

184 lines
4.7 KiB
Go

package pool_test
import (
"bufio"
"context"
"net"
"unsafe"
. "github.com/bsm/ginkgo/v2"
. "github.com/bsm/gomega"
"github.com/redis/go-redis/v9/internal/pool"
"github.com/redis/go-redis/v9/internal/proto"
)
var _ = Describe("Buffer Size Configuration", func() {
var connPool *pool.ConnPool
ctx := context.Background()
AfterEach(func() {
if connPool != nil {
connPool.Close()
}
})
It("should use default buffer sizes when not specified", func() {
connPool = pool.NewConnPool(&pool.Options{
Dialer: dummyDialer,
PoolSize: 1,
PoolTimeout: 1000,
})
cn, err := connPool.NewConn(ctx)
Expect(err).NotTo(HaveOccurred())
defer connPool.CloseConn(cn)
// Check that default buffer sizes are used (0.5MiB)
writerBufSize := getWriterBufSizeUnsafe(cn)
readerBufSize := getReaderBufSizeUnsafe(cn)
Expect(writerBufSize).To(Equal(proto.DefaultBufferSize)) // Default 0.5MiB buffer size
Expect(readerBufSize).To(Equal(proto.DefaultBufferSize)) // Default 0.5MiB buffer size
})
It("should use custom buffer sizes when specified", func() {
customReadSize := 32 * 1024 // 32KB
customWriteSize := 64 * 1024 // 64KB
connPool = pool.NewConnPool(&pool.Options{
Dialer: dummyDialer,
PoolSize: 1,
PoolTimeout: 1000,
ReadBufferSize: customReadSize,
WriteBufferSize: customWriteSize,
})
cn, err := connPool.NewConn(ctx)
Expect(err).NotTo(HaveOccurred())
defer connPool.CloseConn(cn)
// Check that custom buffer sizes are used
writerBufSize := getWriterBufSizeUnsafe(cn)
readerBufSize := getReaderBufSizeUnsafe(cn)
Expect(writerBufSize).To(Equal(customWriteSize))
Expect(readerBufSize).To(Equal(customReadSize))
})
It("should handle zero buffer sizes by using defaults", func() {
connPool = pool.NewConnPool(&pool.Options{
Dialer: dummyDialer,
PoolSize: 1,
PoolTimeout: 1000,
ReadBufferSize: 0, // Should use default
WriteBufferSize: 0, // Should use default
})
cn, err := connPool.NewConn(ctx)
Expect(err).NotTo(HaveOccurred())
defer connPool.CloseConn(cn)
// Check that default buffer sizes are used (0.5MiB)
writerBufSize := getWriterBufSizeUnsafe(cn)
readerBufSize := getReaderBufSizeUnsafe(cn)
Expect(writerBufSize).To(Equal(proto.DefaultBufferSize)) // Default 0.5MiB buffer size
Expect(readerBufSize).To(Equal(proto.DefaultBufferSize)) // Default 0.5MiB buffer size
})
It("should use 0.5MiB default buffer sizes for standalone NewConn", func() {
// Test that NewConn (without pool) also uses 0.5MiB defaults
netConn := newDummyConn()
cn := pool.NewConn(netConn)
defer cn.Close()
writerBufSize := getWriterBufSizeUnsafe(cn)
readerBufSize := getReaderBufSizeUnsafe(cn)
Expect(writerBufSize).To(Equal(proto.DefaultBufferSize)) // Default 0.5MiB buffer size
Expect(readerBufSize).To(Equal(proto.DefaultBufferSize)) // Default 0.5MiB buffer size
})
It("should use 0.5MiB defaults even when pool is created directly without buffer sizes", func() {
// Test the scenario where someone creates a pool directly (like in tests)
// without setting ReadBufferSize and WriteBufferSize
connPool = pool.NewConnPool(&pool.Options{
Dialer: dummyDialer,
PoolSize: 1,
PoolTimeout: 1000,
// ReadBufferSize and WriteBufferSize are not set (will be 0)
})
cn, err := connPool.NewConn(ctx)
Expect(err).NotTo(HaveOccurred())
defer connPool.CloseConn(cn)
// Should still get 0.5MiB defaults because NewConnPool sets them
writerBufSize := getWriterBufSizeUnsafe(cn)
readerBufSize := getReaderBufSizeUnsafe(cn)
Expect(writerBufSize).To(Equal(proto.DefaultBufferSize)) // Default 0.5MiB buffer size
Expect(readerBufSize).To(Equal(proto.DefaultBufferSize)) // Default 0.5MiB buffer size
})
})
// Helper functions to extract buffer sizes using unsafe pointers
func getWriterBufSizeUnsafe(cn *pool.Conn) int {
cnPtr := (*struct {
usedAt int64
netConn net.Conn
rd *proto.Reader
bw *bufio.Writer
wr *proto.Writer
// ... other fields
})(unsafe.Pointer(cn))
if cnPtr.bw == nil {
return -1
}
bwPtr := (*struct {
err error
buf []byte
n int
wr interface{}
})(unsafe.Pointer(cnPtr.bw))
return len(bwPtr.buf)
}
func getReaderBufSizeUnsafe(cn *pool.Conn) int {
cnPtr := (*struct {
usedAt int64
netConn net.Conn
rd *proto.Reader
bw *bufio.Writer
wr *proto.Writer
// ... other fields
})(unsafe.Pointer(cn))
if cnPtr.rd == nil {
return -1
}
rdPtr := (*struct {
rd *bufio.Reader
})(unsafe.Pointer(cnPtr.rd))
if rdPtr.rd == nil {
return -1
}
bufReaderPtr := (*struct {
buf []byte
rd interface{}
r, w int
err error
lastByte int
lastRuneSize int
})(unsafe.Pointer(rdPtr.rd))
return len(bufReaderPtr.buf)
}