Files
godoxy-yusing/internal/utils/synk/pool_test.go
yusing f31b1b5ed3 refactor(misc): enhance performance on bytes pool, entrypoint, access log and route context handling
- Introduced benchmark tests for Entrypoint and ReverseProxy to evaluate performance.
- Updated Entrypoint's ServeHTTP method to improve route context management.
- Added new test file for entrypoint benchmarks and refined existing tests for route handling.
2025-09-14 00:03:27 +08:00

264 lines
8.1 KiB
Go

package synk
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestSized(t *testing.T) {
b := bytesPool.GetSized(2 * SizedPoolThreshold)
assert.Equal(t, cap(b), 2*SizedPoolThreshold)
bytesPool.Put(b)
assert.Equal(t, underlyingPtr(b), underlyingPtr(bytesPool.GetSized(SizedPoolThreshold)))
}
func TestUnsized(t *testing.T) {
b := bytesPool.Get()
assert.Equal(t, cap(b), UnsizedAvg)
bytesPool.Put(b)
assert.Equal(t, underlyingPtr(b), underlyingPtr(bytesPool.Get()))
}
func TestGetSizedExactMatch(t *testing.T) {
// Test exact size match reuse
size := SizedPoolThreshold
b1 := bytesPool.GetSized(size)
assert.Equal(t, size, len(b1))
assert.Equal(t, size, cap(b1))
// Put back into pool
bytesPool.Put(b1)
// Get same size - should reuse the same buffer
b2 := bytesPool.GetSized(size)
assert.Equal(t, size, len(b2))
assert.Equal(t, size, cap(b2))
assert.Equal(t, underlyingPtr(b1), underlyingPtr(b2))
}
func TestGetSizedBufferSplit(t *testing.T) {
// Test buffer splitting when capacity > requested size
largeSize := 2 * SizedPoolThreshold
requestedSize := SizedPoolThreshold
// Create a large buffer and put it in pool
b1 := bytesPool.GetSized(largeSize)
assert.Equal(t, largeSize, len(b1))
assert.Equal(t, largeSize, cap(b1))
bytesPool.Put(b1)
// Request smaller size - should split the buffer
b2 := bytesPool.GetSized(requestedSize)
assert.Equal(t, requestedSize, len(b2))
assert.Equal(t, requestedSize, cap(b2)) // capacity should remain the original
assert.Equal(t, underlyingPtr(b1), underlyingPtr(b2))
// The remaining part should be put back in pool
// Request the remaining size to verify
remainingSize := largeSize - requestedSize
b3 := bytesPool.GetSized(remainingSize)
assert.Equal(t, remainingSize, len(b3))
assert.Equal(t, remainingSize, cap(b3))
// Verify the remaining buffer points to the correct memory location
originalPtr := underlyingPtr(b1)
remainingPtr := underlyingPtr(b3)
// The remaining buffer should start at original + requestedSize
expectedOffset := uintptr(originalPtr) + uintptr(requestedSize)
actualOffset := uintptr(remainingPtr)
assert.Equal(t, expectedOffset, actualOffset, "Remaining buffer should point to correct offset")
}
func TestGetSizedSmallRemainder(t *testing.T) {
// Test when remaining size is smaller than SizedPoolThreshold
poolSize := SizedPoolThreshold + 100 // Just slightly larger than threshold
requestedSize := SizedPoolThreshold
// Create buffer and put in pool
b1 := bytesPool.GetSized(poolSize)
bytesPool.Put(b1)
// Request size that leaves small remainder
b2 := bytesPool.GetSized(requestedSize)
assert.Equal(t, requestedSize, len(b2))
assert.Equal(t, requestedSize, cap(b2))
// The small remainder (100 bytes) should NOT be put back in sized pool
// Try to get the remainder size - should create new buffer
b3 := bytesPool.GetSized(100)
assert.Equal(t, 100, len(b3))
assert.Equal(t, 100, cap(b3))
assert.NotEqual(t, underlyingPtr(b2), underlyingPtr(b3))
}
func TestGetSizedSmallBufferBypass(t *testing.T) {
// Test that small buffers (< SizedPoolThreshold) don't use sized pool
smallSize := SizedPoolThreshold - 1
b1 := bytesPool.GetSized(smallSize)
assert.Equal(t, smallSize, len(b1))
assert.Equal(t, smallSize, cap(b1))
b2 := bytesPool.GetSized(smallSize)
assert.Equal(t, smallSize, len(b2))
assert.Equal(t, smallSize, cap(b2))
// Should be different buffers (not pooled)
assert.NotEqual(t, underlyingPtr(b1), underlyingPtr(b2))
}
func TestGetSizedBufferTooSmall(t *testing.T) {
// Test when pool buffer is smaller than requested size
smallSize := SizedPoolThreshold
largeSize := 2 * SizedPoolThreshold
// Put small buffer in pool
b1 := bytesPool.GetSized(smallSize)
bytesPool.Put(b1)
// Request larger size - should create new buffer, not reuse small one
b2 := bytesPool.GetSized(largeSize)
assert.Equal(t, largeSize, len(b2))
assert.Equal(t, largeSize, cap(b2))
assert.NotEqual(t, underlyingPtr(b1), underlyingPtr(b2))
// The small buffer should still be in pool
b3 := bytesPool.GetSized(smallSize)
assert.Equal(t, underlyingPtr(b1), underlyingPtr(b3))
}
func TestGetSizedMultipleSplits(t *testing.T) {
// Test multiple sequential splits of the same buffer
hugeSize := 4 * SizedPoolThreshold
splitSize := SizedPoolThreshold
// Create huge buffer
b1 := bytesPool.GetSized(hugeSize)
originalPtr := underlyingPtr(b1)
bytesPool.Put(b1)
// Split it into smaller pieces
pieces := make([][]byte, 0, 4)
for i := range 4 {
piece := bytesPool.GetSized(splitSize)
pieces = append(pieces, piece)
// Each piece should point to the correct offset
expectedOffset := uintptr(originalPtr) + uintptr(i*splitSize)
actualOffset := uintptr(underlyingPtr(piece))
assert.Equal(t, expectedOffset, actualOffset, "Piece %d should point to correct offset", i)
assert.Equal(t, splitSize, len(piece))
assert.Equal(t, splitSize, cap(piece))
}
// All pieces should have the same underlying capacity
for i, piece := range pieces {
assert.Equal(t, splitSize, cap(piece), "Piece %d should have correct capacity", i)
}
}
func TestGetSizedMemorySafety(t *testing.T) {
// Test that split buffers don't interfere with each other
totalSize := 3 * SizedPoolThreshold
firstSize := SizedPoolThreshold
// Create buffer and split it
b1 := bytesPool.GetSized(totalSize)
// Fill with test data
for i := range len(b1) {
b1[i] = byte(i % 256)
}
bytesPool.Put(b1)
// Get first part
first := bytesPool.GetSized(firstSize)
assert.Equal(t, firstSize, len(first))
// Verify data integrity
for i := range len(first) {
assert.Equal(t, byte(i%256), first[i], "Data should be preserved after split")
}
// Get remaining part
remainingSize := totalSize - firstSize
remaining := bytesPool.GetSized(remainingSize)
assert.Equal(t, remainingSize, len(remaining))
// Verify remaining data
for i := range len(remaining) {
expected := byte((i + firstSize) % 256)
assert.Equal(t, expected, remaining[i], "Remaining data should be preserved")
}
}
func TestGetSizedCapacityLimiting(t *testing.T) {
// Test that returned buffers have limited capacity to prevent overwrites
largeSize := 2 * SizedPoolThreshold
requestedSize := SizedPoolThreshold
// Create large buffer and put in pool
b1 := bytesPool.GetSized(largeSize)
bytesPool.Put(b1)
// Get smaller buffer from the split
b2 := bytesPool.GetSized(requestedSize)
assert.Equal(t, requestedSize, len(b2))
assert.Equal(t, requestedSize, cap(b2), "Returned buffer should have limited capacity")
// Try to append data - should not be able to overwrite beyond capacity
original := make([]byte, len(b2))
copy(original, b2)
// This append should force a new allocation since capacity is limited
b2 = append(b2, 1, 2, 3, 4, 5)
assert.Greater(t, len(b2), requestedSize, "Buffer should have grown")
// Get the remaining buffer to verify it wasn't affected
remainingSize := largeSize - requestedSize
b3 := bytesPool.GetSized(remainingSize)
assert.Equal(t, remainingSize, len(b3))
assert.Equal(t, remainingSize, cap(b3), "Remaining buffer should have limited capacity")
}
func TestGetSizedAppendSafety(t *testing.T) {
// Test that appending to returned buffer doesn't affect remaining buffer
totalSize := 4 * SizedPoolThreshold
firstSize := SizedPoolThreshold
// Create buffer with specific pattern
b1 := bytesPool.GetSized(totalSize)
for i := range len(b1) {
b1[i] = byte(100 + i%100)
}
bytesPool.Put(b1)
// Get first part
first := bytesPool.GetSized(firstSize)
assert.Equal(t, firstSize, cap(first), "First part should have limited capacity")
// Store original first part content
originalFirst := make([]byte, len(first))
copy(originalFirst, first)
// Get remaining part to establish its state
remaining := bytesPool.GetSized(SizedPoolThreshold)
// Store original remaining content
originalRemaining := make([]byte, len(remaining))
copy(originalRemaining, remaining)
// Now try to append to first - this should not affect remaining buffers
// since capacity is limited
first = append(first, make([]byte, 1000)...)
// Verify remaining buffer content is unchanged
for i := range len(originalRemaining) {
assert.Equal(t, originalRemaining[i], remaining[i],
"Remaining buffer should be unaffected by append to first buffer")
}
}