Porter Memory Infrastructure
The memory infrastructure package provides a thread-safe memory allocation tracking system built on top of Apache Arrow's memory allocator. It enables precise monitoring of memory usage across the application while maintaining compatibility with Arrow's memory management system.
Design Overview
Core Components
-
TrackedAllocator
type TrackedAllocator struct {
underlying memory.Allocator
bytesUsed atomic.Int64
}
-
Global Allocator
var globalAllocator = NewTrackedAllocator(memory.NewGoAllocator())
Implementation Details
Memory Tracking
The TrackedAllocator wraps Apache Arrow's memory allocator to provide:
-
Byte Usage Tracking
- Atomic counter for total allocated bytes
- Thread-safe operations
- Real-time memory usage monitoring
-
Memory Operations
// Allocation
func (a *TrackedAllocator) Allocate(size int) []byte
// Reallocation
func (a *TrackedAllocator) Reallocate(size int, b []byte) []byte
// Deallocation
func (a *TrackedAllocator) Free(b []byte)
// Usage Query
func (a *TrackedAllocator) BytesUsed() int64
Thread Safety
The implementation ensures thread safety through:
-
Atomic Operations
- Atomic counter for byte tracking
- No locks required for basic operations
- Safe concurrent access
-
Concurrent Usage
- Safe for multiple goroutines
- Consistent memory accounting
- No race conditions
Usage
Basic Usage
// Get the global tracked allocator
allocator := memory.GetAllocator()
// Allocate memory
buf := allocator.Allocate(1024)
// Check memory usage
bytesUsed := allocator.(*memory.TrackedAllocator).BytesUsed()
// Free memory
allocator.Free(buf)
Custom Allocator
// Create a custom tracked allocator
underlying := memory.NewGoAllocator()
trackedAllocator := memory.NewTrackedAllocator(underlying)
// Use with Arrow operations
builder := array.NewInt32Builder(trackedAllocator)
Memory Management
Allocation Patterns
-
Direct Allocation
- Simple memory allocation
- Immediate tracking
- Direct byte counting
-
Reallocation
- Size adjustment tracking
- Delta calculation
- Accurate byte accounting
-
Deallocation
- Proper cleanup
- Usage reduction
- Resource release
Memory Monitoring
-
Usage Tracking
- Real-time byte counting
- Allocation patterns
- Memory pressure detection
-
Performance Impact
- Minimal overhead
- Atomic operations
- Efficient tracking
Best Practices
-
Memory Management
- Always free allocated memory
- Monitor usage patterns
- Set appropriate limits
-
Concurrency
- Use atomic operations
- Avoid manual synchronization
- Handle concurrent access
-
Resource Cleanup
- Proper deallocation
- Usage verification
- Leak prevention
-
Monitoring
- Track usage patterns
- Set alerts
- Monitor trends
Testing
The package includes comprehensive tests covering:
-
Basic Operations
- Allocation
- Reallocation
- Deallocation
-
Concurrency
- Multiple goroutines
- Atomic operations
- Thread safety
-
Edge Cases
- Zero-size allocations
- Large allocations
- Reallocation patterns
-
Overhead
- Minimal tracking overhead
- Atomic operations
- Efficient byte counting
-
Memory Efficiency
- Accurate tracking
- Proper cleanup
- Resource optimization
-
Concurrency
- Lock-free operations
- Scalable design
- Thread safety
Integration
Arrow Integration
// Use with Arrow builders
builder := array.NewInt32Builder(memory.GetAllocator())
// Use with Arrow arrays
arr := array.NewInt32Data(
array.NewData(
arrow.PrimitiveTypes.Int32,
10,
[]*memory.Buffer{nil, buf},
nil,
0,
0,
),
)
Custom Integration
// Create custom tracked allocator
type CustomAllocator struct {
*memory.TrackedAllocator
// Additional fields
}
// Implement custom allocation logic
func (a *CustomAllocator) Allocate(size int) []byte {
// Custom allocation logic
return a.TrackedAllocator.Allocate(size)
}