Enterprise Go Memory Management: Weak Pointers & Performance Guide 2025
Enterprise Go Memory Management: Weak Pointers & Performance Guide 2025
Introduction
Enterprise Go memory management in 2025 requires deep understanding of garbage collection, weak pointers, memory optimization patterns, and performance tuning techniques. This comprehensive guide covers advanced memory management strategies, Go 1.24 weak pointer implementation, GC optimization, and production-grade memory patterns for high-performance enterprise systems.
Chapter 1: Advanced Memory Management Patterns
Enterprise Memory Pool Management
// Enterprise memory pool management system
package memory
import (
"runtime"
"sync"
"sync/atomic"
"time"
"unsafe"
"github.com/prometheus/client_golang/prometheus"
)
// EnterpriseMemoryManager provides comprehensive memory management
type EnterpriseMemoryManager struct {
pools map[string]*MemoryPool
weakRefs *WeakReferenceManager
gcOptimizer *GCOptimizer
metrics *MemoryMetrics
// Configuration
config *MemoryConfig
// Monitoring
monitor *MemoryMonitor
// Pool management
poolMutex sync.RWMutex
// Statistics
stats *MemoryStats
lastGCTime time.Time
}
type MemoryConfig struct {
EnableWeakRefs bool
EnablePooling bool
EnableGCOptimization bool
MaxPoolSize int64
PoolGrowthFactor float64
GCTargetPercent int
GCMemoryLimit int64
// Advanced features
EnableArenas bool
EnableProfiling bool
EnableMetrics bool
}
type MemoryPool struct {
name string
objectSize int
maxObjects int
objects []unsafe.Pointer
available []bool
allocCounter int64
freeCounter int64
// Memory alignment
alignment int
// Statistics
hitRate float64
allocTime time.Duration
mutex sync.Mutex
}
// Create enterprise memory manager
func NewEnterpriseMemoryManager(config *MemoryConfig) *EnterpriseMemoryManager {
emm := &EnterpriseMemoryManager{
pools: make(map[string]*MemoryPool),
config: config,
stats: &MemoryStats{},
}
// Initialize weak reference manager
if config.EnableWeakRefs {
emm.weakRefs = NewWeakReferenceManager()
}
// Initialize GC optimizer
if config.EnableGCOptimization {
emm.gcOptimizer = NewGCOptimizer(config)
}
// Initialize metrics
if config.EnableMetrics {
emm.metrics = NewMemoryMetrics()
}
// Start monitoring
emm.monitor = NewMemoryMonitor(emm)
go emm.monitor.Start()
return emm
}
// Advanced object pooling with type safety
func (emm *EnterpriseMemoryManager) GetPool(name string, objectSize int) *MemoryPool {
emm.poolMutex.RLock()
pool, exists := emm.pools[name]
emm.poolMutex.RUnlock()
if exists {
return pool
}
emm.poolMutex.Lock()
defer emm.poolMutex.Unlock()
// Double-check after acquiring write lock
if pool, exists := emm.pools[name]; exists {
return pool
}
// Create new pool
pool = &MemoryPool{
name: name,
objectSize: objectSize,
maxObjects: emm.config.MaxPoolSize,
objects: make([]unsafe.Pointer, 0, emm.config.MaxPoolSize),
available: make([]bool, emm.config.MaxPoolSize),
alignment: calculateAlignment(objectSize),
}
// Pre-allocate objects
pool.preallocate()
emm.pools[name] = pool
return pool
}
// Allocate object from pool
func (mp *MemoryPool) Allocate() unsafe.Pointer {
mp.mutex.Lock()
defer mp.mutex.Unlock()
start := time.Now()
defer func() {
mp.allocTime = time.Since(start)
}()
// Find available object
for i, available := range mp.available {
if available && i < len(mp.objects) {
mp.available[i] = false
atomic.AddInt64(&mp.allocCounter, 1)
mp.updateHitRate()
return mp.objects[i]
}
}
// No available objects, allocate new one if within limits
if len(mp.objects) < mp.maxObjects {
ptr := allocateAligned(mp.objectSize, mp.alignment)
mp.objects = append(mp.objects, ptr)
index := len(mp.objects) - 1
// Extend available slice if needed
for len(mp.available) <= index {
mp.available = append(mp.available, true)
}
mp.available[index] = false
atomic.AddInt64(&mp.allocCounter, 1)
return ptr
}
// Pool exhausted, allocate directly
return allocateAligned(mp.objectSize, mp.alignment)
}
// Release object back to pool
func (mp *MemoryPool) Release(ptr unsafe.Pointer) {
mp.mutex.Lock()
defer mp.mutex.Unlock()
// Find object in pool
for i, obj := range mp.objects {
if obj == ptr {
mp.available[i] = true
atomic.AddInt64(&mp.freeCounter, 1)
// Clear object memory for security
clearMemory(ptr, mp.objectSize)
return
}
}
// Object not from pool, free directly
freeAligned(ptr)
}
// Pre-allocate pool objects
func (mp *MemoryPool) preallocate() {
initialSize := min(mp.maxObjects/4, 100) // Pre-allocate 25% or 100 objects
for i := 0; i < initialSize; i++ {
ptr := allocateAligned(mp.objectSize, mp.alignment)
mp.objects = append(mp.objects, ptr)
mp.available[i] = true
}
}
// Calculate optimal alignment for object size
func calculateAlignment(size int) int {
// Use cache line alignment for larger objects
if size >= 64 {
return 64
}
// Use word alignment for smaller objects
if size >= 8 {
return 8
}
return 4
}
// Allocate aligned memory
func allocateAligned(size, alignment int) unsafe.Pointer {
// Calculate required size with alignment padding
alignedSize := (size + alignment - 1) &^ (alignment - 1)
// Allocate extra space for alignment
raw := make([]byte, alignedSize+alignment)
// Calculate aligned address
addr := uintptr(unsafe.Pointer(&raw[0]))
aligned := (addr + uintptr(alignment) - 1) &^ (uintptr(alignment) - 1)
return unsafe.Pointer(aligned)
}
// Free aligned memory
func freeAligned(ptr unsafe.Pointer) {
// In Go, we rely on GC for cleanup
// This is a placeholder for explicit memory management if needed
}
// Clear memory for security
func clearMemory(ptr unsafe.Pointer, size int) {
slice := (*[1 << 30]byte)(ptr)[:size:size]
for i := range slice {
slice[i] = 0
}
}
// Update hit rate statistics
func (mp *MemoryPool) updateHitRate() {
allocs := atomic.LoadInt64(&mp.allocCounter)
if allocs > 0 {
hits := allocs - int64(len(mp.objects))
if hits < 0 {
hits = 0
}
mp.hitRate = float64(hits) / float64(allocs)
}
}
// Go 1.24 Weak Pointer Implementation
type WeakReferenceManager struct {
references map[uintptr]*WeakReference
mutex sync.RWMutex
// Cleanup management
cleanupQueue chan *WeakReference
stopCleanup chan struct{}
// Statistics
totalRefs int64
activeRefs int64
cleanedRefs int64
}
type WeakReference struct {
id uintptr
ptr unsafe.Pointer
callback func()
finalizer func(interface{})
alive int32 // atomic flag
// Metadata
createdAt time.Time
size int
typename string
}
// Create weak reference manager
func NewWeakReferenceManager() *WeakReferenceManager {
wrm := &WeakReferenceManager{
references: make(map[uintptr]*WeakReference),
cleanupQueue: make(chan *WeakReference, 1000),
stopCleanup: make(chan struct{}),
}
// Start cleanup goroutine
go wrm.cleanupLoop()
return wrm
}
// Create weak reference to object
func (wrm *WeakReferenceManager) NewWeakRef(obj interface{}, callback func()) *WeakReference {
if obj == nil {
return nil
}
ptr := unsafe.Pointer(&obj)
id := uintptr(ptr)
ref := &WeakReference{
id: id,
ptr: ptr,
callback: callback,
alive: 1,
createdAt: time.Now(),
size: int(unsafe.Sizeof(obj)),
typename: getTypeName(obj),
}
// Set finalizer
runtime.SetFinalizer(&obj, func(obj interface{}) {
wrm.markForCleanup(ref)
})
wrm.mutex.Lock()
wrm.references[id] = ref
atomic.AddInt64(&wrm.totalRefs, 1)
atomic.AddInt64(&wrm.activeRefs, 1)
wrm.mutex.Unlock()
return ref
}
// Get object from weak reference
func (ref *WeakReference) Get() interface{} {
if atomic.LoadInt32(&ref.alive) == 0 {
return nil
}
// Try to recover object from pointer
// Note: This is a simplified implementation
// Real weak pointers require runtime support
return *(*interface{})(ref.ptr)
}
// Check if reference is still alive
func (ref *WeakReference) IsAlive() bool {
return atomic.LoadInt32(&ref.alive) != 0
}
// Mark reference for cleanup
func (wrm *WeakReferenceManager) markForCleanup(ref *WeakReference) {
if atomic.CompareAndSwapInt32(&ref.alive, 1, 0) {
select {
case wrm.cleanupQueue <- ref:
default:
// Queue full, cleanup directly
wrm.cleanup(ref)
}
}
}
// Cleanup loop
func (wrm *WeakReferenceManager) cleanupLoop() {
ticker := time.NewTicker(time.Second)
defer ticker.Stop()
for {
select {
case ref := <-wrm.cleanupQueue:
wrm.cleanup(ref)
case <-ticker.C:
wrm.cleanupExpired()
case <-wrm.stopCleanup:
return
}
}
}
// Cleanup individual reference
func (wrm *WeakReferenceManager) cleanup(ref *WeakReference) {
wrm.mutex.Lock()
delete(wrm.references, ref.id)
wrm.mutex.Unlock()
if ref.callback != nil {
ref.callback()
}
atomic.AddInt64(&wrm.activeRefs, -1)
atomic.AddInt64(&wrm.cleanedRefs, 1)
}
// Cleanup expired references
func (wrm *WeakReferenceManager) cleanupExpired() {
wrm.mutex.RLock()
var expired []*WeakReference
for _, ref := range wrm.references {
if atomic.LoadInt32(&ref.alive) == 0 {
expired = append(expired, ref)
}
}
wrm.mutex.RUnlock()
for _, ref := range expired {
wrm.cleanup(ref)
}
}
// Advanced GC optimization
type GCOptimizer struct {
config *MemoryConfig
lastGCStats runtime.MemStats
gcTriggerCount int64
gcDuration time.Duration
// Optimization strategies
strategies []GCStrategy
currentStrategy int
// Monitoring
metrics *GCMetrics
mutex sync.RWMutex
}
type GCStrategy interface {
Name() string
Apply(config *MemoryConfig) error
Evaluate(stats *runtime.MemStats) float64 // Performance score
}
type GCMetrics struct {
GCCount prometheus.Counter
GCDuration prometheus.Histogram
HeapSize prometheus.Gauge
HeapObjects prometheus.Gauge
GCCPUPercentage prometheus.Gauge
}
// Create GC optimizer
func NewGCOptimizer(config *MemoryConfig) *GCOptimizer {
gco := &GCOptimizer{
config: config,
strategies: make([]GCStrategy, 0),
metrics: NewGCMetrics(),
}
// Register optimization strategies
gco.registerStrategies()
// Set initial GC parameters
if config.GCTargetPercent > 0 {
runtime.GC()
debug.SetGCPercent(config.GCTargetPercent)
}
if config.GCMemoryLimit > 0 {
debug.SetMemoryLimit(config.GCMemoryLimit)
}
return gco
}
// Register GC optimization strategies
func (gco *GCOptimizer) registerStrategies() {
gco.strategies = append(gco.strategies,
&AdaptiveGCStrategy{},
&LowLatencyGCStrategy{},
&HighThroughputGCStrategy{},
&MemoryEfficientGCStrategy{},
)
}
// Optimize GC parameters based on current conditions
func (gco *GCOptimizer) Optimize() {
var stats runtime.MemStats
runtime.ReadMemStats(&stats)
gco.mutex.Lock()
defer gco.mutex.Unlock()
// Update metrics
gco.updateMetrics(&stats)
// Evaluate current strategy
currentScore := gco.strategies[gco.currentStrategy].Evaluate(&stats)
// Try other strategies
bestStrategy := gco.currentStrategy
bestScore := currentScore
for i, strategy := range gco.strategies {
if i == gco.currentStrategy {
continue
}
score := strategy.Evaluate(&stats)
if score > bestScore {
bestScore = score
bestStrategy = i
}
}
// Switch to better strategy if found
if bestStrategy != gco.currentStrategy {
gco.strategies[bestStrategy].Apply(gco.config)
gco.currentStrategy = bestStrategy
}
gco.lastGCStats = stats
}
// Update GC metrics
func (gco *GCOptimizer) updateMetrics(stats *runtime.MemStats) {
gco.metrics.GCCount.Add(float64(stats.NumGC - gco.lastGCStats.NumGC))
gco.metrics.HeapSize.Set(float64(stats.HeapSys))
gco.metrics.HeapObjects.Set(float64(stats.HeapObjects))
// Calculate GC CPU percentage
if stats.GCCPUFraction > 0 {
gco.metrics.GCCPUPercentage.Set(stats.GCCPUFraction * 100)
}
}
// Adaptive GC strategy
type AdaptiveGCStrategy struct {
basePercent int
adjustmentRate float64
targetLatency time.Duration
}
func (ags *AdaptiveGCStrategy) Name() string {
return "adaptive"
}
func (ags *AdaptiveGCStrategy) Apply(config *MemoryConfig) error {
// Adjust GC percentage based on memory pressure
var stats runtime.MemStats
runtime.ReadMemStats(&stats)
heapUsage := float64(stats.HeapInuse) / float64(stats.HeapSys)
var newPercent int
if heapUsage > 0.8 {
// High memory pressure, be more aggressive
newPercent = max(50, config.GCTargetPercent-20)
} else if heapUsage < 0.3 {
// Low memory pressure, be less aggressive
newPercent = min(200, config.GCTargetPercent+50)
} else {
newPercent = config.GCTargetPercent
}
debug.SetGCPercent(newPercent)
return nil
}
func (ags *AdaptiveGCStrategy) Evaluate(stats *runtime.MemStats) float64 {
// Score based on balance of latency and throughput
latencyScore := 1.0 - (stats.GCCPUFraction * 10) // Lower GC CPU is better
memoryScore := 1.0 - (float64(stats.HeapInuse) / float64(stats.HeapSys))
return (latencyScore + memoryScore) / 2.0
}
// Low latency GC strategy
type LowLatencyGCStrategy struct{}
func (llgs *LowLatencyGCStrategy) Name() string {
return "low_latency"
}
func (llgs *LowLatencyGCStrategy) Apply(config *MemoryConfig) error {
// Set aggressive GC to minimize pause times
debug.SetGCPercent(50)
return nil
}
func (llgs *LowLatencyGCStrategy) Evaluate(stats *runtime.MemStats) float64 {
// Score based primarily on GC pause times
return 1.0 - (stats.GCCPUFraction * 20)
}
// High throughput GC strategy
type HighThroughputGCStrategy struct{}
func (htgs *HighThroughputGCStrategy) Name() string {
return "high_throughput"
}
func (htgs *HighThroughputGCStrategy) Apply(config *MemoryConfig) error {
// Set conservative GC to maximize throughput
debug.SetGCPercent(200)
return nil
}
func (htgs *HighThroughputGCStrategy) Evaluate(stats *runtime.MemStats) float64 {
// Score based on allocation rate vs GC overhead
allocRate := float64(stats.TotalAlloc) / float64(time.Now().Unix())
gcOverhead := stats.GCCPUFraction
return allocRate * (1.0 - gcOverhead*5)
}
// Memory efficient GC strategy
type MemoryEfficientGCStrategy struct{}
func (megs *MemoryEfficientGCStrategy) Name() string {
return "memory_efficient"
}
func (megs *MemoryEfficientGCStrategy) Apply(config *MemoryConfig) error {
// Set moderate GC for memory efficiency
debug.SetGCPercent(75)
// Force GC to clean up memory
runtime.GC()
return nil
}
func (megs *MemoryEfficientGCStrategy) Evaluate(stats *runtime.MemStats) float64 {
// Score based on memory utilization efficiency
heapEfficiency := float64(stats.HeapInuse) / float64(stats.HeapSys)
return heapEfficiency
}
// Memory monitoring and profiling
type MemoryMonitor struct {
manager *EnterpriseMemoryManager
interval time.Duration
stopChan chan struct{}
// Profiling
enablePprof bool
profiles []*MemoryProfile
// Alerts
alertThresholds map[string]float64
alertCallbacks map[string]func(MemoryAlert)
}
type MemoryProfile struct {
Timestamp time.Time
HeapSize int64
HeapObjects int64
GoroutineCount int64
GCCount int64
AllocRate float64
}
type MemoryAlert struct {
Type string
Severity string
Message string
Timestamp time.Time
Value float64
Threshold float64
}
// Create memory monitor
func NewMemoryMonitor(manager *EnterpriseMemoryManager) *MemoryMonitor {
return &MemoryMonitor{
manager: manager,
interval: time.Minute,
stopChan: make(chan struct{}),
enablePprof: manager.config.EnableProfiling,
alertThresholds: make(map[string]float64),
alertCallbacks: make(map[string]func(MemoryAlert)),
}
}
// Start monitoring
func (mm *MemoryMonitor) Start() {
ticker := time.NewTicker(mm.interval)
defer ticker.Stop()
for {
select {
case <-ticker.C:
mm.collectMetrics()
mm.checkAlerts()
if mm.enablePprof {
mm.captureProfile()
}
case <-mm.stopChan:
return
}
}
}
// Collect memory metrics
func (mm *MemoryMonitor) collectMetrics() {
var stats runtime.MemStats
runtime.ReadMemStats(&stats)
profile := &MemoryProfile{
Timestamp: time.Now(),
HeapSize: int64(stats.HeapSys),
HeapObjects: int64(stats.HeapObjects),
GoroutineCount: int64(runtime.NumGoroutine()),
GCCount: int64(stats.NumGC),
AllocRate: calculateAllocRate(&stats),
}
mm.profiles = append(mm.profiles, profile)
// Keep only recent profiles
if len(mm.profiles) > 1000 {
mm.profiles = mm.profiles[len(mm.profiles)-1000:]
}
// Update manager statistics
mm.manager.stats.update(profile)
}
// Check memory alerts
func (mm *MemoryMonitor) checkAlerts() {
var stats runtime.MemStats
runtime.ReadMemStats(&stats)
// Check heap usage
if threshold, exists := mm.alertThresholds["heap_usage"]; exists {
usage := float64(stats.HeapInuse) / float64(stats.HeapSys)
if usage > threshold {
mm.sendAlert(MemoryAlert{
Type: "heap_usage",
Severity: "warning",
Message: "High heap usage detected",
Value: usage,
Threshold: threshold,
Timestamp: time.Now(),
})
}
}
// Check GC frequency
if threshold, exists := mm.alertThresholds["gc_frequency"]; exists {
gcRate := calculateGCRate(&stats)
if gcRate > threshold {
mm.sendAlert(MemoryAlert{
Type: "gc_frequency",
Severity: "warning",
Message: "High GC frequency detected",
Value: gcRate,
Threshold: threshold,
Timestamp: time.Now(),
})
}
}
}
// Send memory alert
func (mm *MemoryMonitor) sendAlert(alert MemoryAlert) {
if callback, exists := mm.alertCallbacks[alert.Type]; exists {
callback(alert)
}
}
// Capture memory profile
func (mm *MemoryMonitor) captureProfile() {
// This would integrate with pprof for detailed profiling
// Implementation depends on specific profiling requirements
}
// Memory statistics
type MemoryStats struct {
TotalAllocations int64
CurrentHeapSize int64
PeakHeapSize int64
GCCount int64
LastGCDuration time.Duration
// Pool statistics
PoolHitRate float64
PoolMissRate float64
mutex sync.RWMutex
}
// Update statistics
func (ms *MemoryStats) update(profile *MemoryProfile) {
ms.mutex.Lock()
defer ms.mutex.Unlock()
ms.CurrentHeapSize = profile.HeapSize
if profile.HeapSize > ms.PeakHeapSize {
ms.PeakHeapSize = profile.HeapSize
}
ms.GCCount = profile.GCCount
}
// Helper functions
func getTypeName(obj interface{}) string {
return fmt.Sprintf("%T", obj)
}
func calculateAllocRate(stats *runtime.MemStats) float64 {
// Simplified allocation rate calculation
return float64(stats.TotalAlloc) / float64(time.Now().Unix())
}
func calculateGCRate(stats *runtime.MemStats) float64 {
// Simplified GC rate calculation
return float64(stats.NumGC) / float64(time.Now().Unix())
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
// Metrics initialization
func NewMemoryMetrics() *MemoryMetrics {
return &MemoryMetrics{
PoolHitRate: prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Name: "memory_pool_hit_rate",
Help: "Memory pool hit rate percentage",
},
[]string{"pool_name"},
),
PoolSize: prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Name: "memory_pool_size",
Help: "Current memory pool size",
},
[]string{"pool_name"},
),
WeakReferences: prometheus.NewGauge(
prometheus.GaugeOpts{
Name: "weak_references_active",
Help: "Number of active weak references",
},
),
}
}
func NewGCMetrics() *GCMetrics {
return &GCMetrics{
GCCount: prometheus.NewCounter(
prometheus.CounterOpts{
Name: "gc_collections_total",
Help: "Total number of GC collections",
},
),
GCDuration: prometheus.NewHistogram(
prometheus.HistogramOpts{
Name: "gc_duration_seconds",
Help: "GC pause duration in seconds",
Buckets: prometheus.ExponentialBuckets(0.0001, 2, 15),
},
),
HeapSize: prometheus.NewGauge(
prometheus.GaugeOpts{
Name: "heap_size_bytes",
Help: "Current heap size in bytes",
},
),
HeapObjects: prometheus.NewGauge(
prometheus.GaugeOpts{
Name: "heap_objects_total",
Help: "Number of objects in heap",
},
),
GCCPUPercentage: prometheus.NewGauge(
prometheus.GaugeOpts{
Name: "gc_cpu_percentage",
Help: "GC CPU usage percentage",
},
),
}
}
type MemoryMetrics struct {
PoolHitRate *prometheus.GaugeVec
PoolSize *prometheus.GaugeVec
WeakReferences prometheus.Gauge
}
Chapter 2: Go 1.24 Weak Pointer Implementation
Advanced Weak Reference Patterns
// Go 1.24 weak pointer implementation
package weakptr
import (
"reflect"
"runtime"
"sync"
"sync/atomic"
"unsafe"
)
// WeakPointer represents a weak reference that doesn't prevent garbage collection
type WeakPointer[T any] struct {
ptr unsafe.Pointer
id uintptr
cleanup func()
valid int32 // atomic flag
// Type information
typeInfo *TypeInfo
// Metadata
metadata *WeakPtrMetadata
}
type TypeInfo struct {
Type reflect.Type
Size uintptr
Align uintptr
Kind reflect.Kind
}
type WeakPtrMetadata struct {
CreatedAt int64 // Unix timestamp
AccessCount int64 // Atomic counter
LastAccess int64 // Unix timestamp
SourceInfo string // Debug information
}
// Global weak pointer registry
var (
globalRegistry = &WeakPtrRegistry{
pointers: make(map[uintptr]*WeakPointerEntry),
cleanup: make(chan *WeakPointerEntry, 1000),
}
)
type WeakPtrRegistry struct {
pointers map[uintptr]*WeakPointerEntry
cleanup chan *WeakPointerEntry
mutex sync.RWMutex
// Statistics
totalCreated int64
totalCleaned int64
activeCount int64
}
type WeakPointerEntry struct {
id uintptr
weakPtr interface{} // Actual weak pointer
finalizer func()
typeInfo *TypeInfo
}
// Create new weak pointer
func NewWeakPointer[T any](obj *T) *WeakPointer[T] {
if obj == nil {
return nil
}
ptr := unsafe.Pointer(obj)
id := uintptr(ptr)
// Get type information
typeInfo := &TypeInfo{
Type: reflect.TypeOf(*obj),
Size: unsafe.Sizeof(*obj),
Align: unsafe.Alignof(*obj),
Kind: reflect.TypeOf(*obj).Kind(),
}
// Create metadata
metadata := &WeakPtrMetadata{
CreatedAt: time.Now().Unix(),
SourceInfo: getCallerInfo(),
}
weak := &WeakPointer[T]{
ptr: ptr,
id: id,
valid: 1,
typeInfo: typeInfo,
metadata: metadata,
}
// Register with global registry
globalRegistry.register(weak)
// Set up finalizer for the original object
runtime.SetFinalizer(obj, func(obj *T) {
weak.invalidate()
globalRegistry.markForCleanup(id)
})
return weak
}
// Get the referenced object
func (wp *WeakPointer[T]) Get() *T {
if !wp.IsValid() {
return nil
}
// Update access statistics
atomic.AddInt64(&wp.metadata.AccessCount, 1)
atomic.StoreInt64(&wp.metadata.LastAccess, time.Now().Unix())
// Attempt to recover the object
// Note: This requires runtime support for true weak pointers
return (*T)(wp.ptr)
}
// Check if the weak pointer is still valid
func (wp *WeakPointer[T]) IsValid() bool {
return atomic.LoadInt32(&wp.valid) != 0
}
// Invalidate the weak pointer
func (wp *WeakPointer[T]) invalidate() {
if atomic.CompareAndSwapInt32(&wp.valid, 1, 0) {
if wp.cleanup != nil {
wp.cleanup()
}
}
}
// Set cleanup callback
func (wp *WeakPointer[T]) SetCleanup(cleanup func()) {
wp.cleanup = cleanup
}
// Get metadata
func (wp *WeakPointer[T]) Metadata() *WeakPtrMetadata {
return wp.metadata
}
// Get type information
func (wp *WeakPointer[T]) TypeInfo() *TypeInfo {
return wp.typeInfo
}
// Register weak pointer with global registry
func (wpr *WeakPtrRegistry) register(weak interface{}) {
wpr.mutex.Lock()
defer wpr.mutex.Unlock()
var id uintptr
switch w := weak.(type) {
case *WeakPointer[any]:
id = w.id
default:
// Handle other weak pointer types
return
}
entry := &WeakPointerEntry{
id: id,
weakPtr: weak,
}
wpr.pointers[id] = entry
atomic.AddInt64(&wpr.totalCreated, 1)
atomic.AddInt64(&wpr.activeCount, 1)
}
// Mark weak pointer for cleanup
func (wpr *WeakPtrRegistry) markForCleanup(id uintptr) {
wpr.mutex.RLock()
entry, exists := wpr.pointers[id]
wpr.mutex.RUnlock()
if exists {
select {
case wpr.cleanup <- entry:
default:
// Cleanup queue full, clean immediately
wpr.cleanupEntry(entry)
}
}
}
// Cleanup entry
func (wpr *WeakPtrRegistry) cleanupEntry(entry *WeakPointerEntry) {
wpr.mutex.Lock()
delete(wpr.pointers, entry.id)
wpr.mutex.Unlock()
if entry.finalizer != nil {
entry.finalizer()
}
atomic.AddInt64(&wpr.totalCleaned, 1)
atomic.AddInt64(&wpr.activeCount, -1)
}
// Advanced weak pointer patterns for caches
type WeakCache[K comparable, V any] struct {
entries map[K]*WeakCacheEntry[V]
mutex sync.RWMutex
// Statistics
hits int64
misses int64
// Configuration
maxSize int
ttl time.Duration
onEvict func(K, *V)
}
type WeakCacheEntry[V any] struct {
weakPtr *WeakPointer[V]
createdAt time.Time
lastAccess time.Time
hitCount int64
}
// Create new weak cache
func NewWeakCache[K comparable, V any](maxSize int, ttl time.Duration) *WeakCache[K, V] {
cache := &WeakCache[K, V]{
entries: make(map[K]*WeakCacheEntry[V]),
maxSize: maxSize,
ttl: ttl,
}
// Start cleanup goroutine
go cache.cleanupLoop()
return cache
}
// Store value in weak cache
func (wc *WeakCache[K, V]) Store(key K, value *V) {
if value == nil {
return
}
wc.mutex.Lock()
defer wc.mutex.Unlock()
// Create weak pointer
weakPtr := NewWeakPointer(value)
if weakPtr == nil {
return
}
// Set cleanup callback to remove from cache
weakPtr.SetCleanup(func() {
wc.remove(key)
})
// Create cache entry
entry := &WeakCacheEntry[V]{
weakPtr: weakPtr,
createdAt: time.Now(),
lastAccess: time.Now(),
}
// Store in cache
wc.entries[key] = entry
// Enforce size limit
if len(wc.entries) > wc.maxSize {
wc.evictOldest()
}
}
// Load value from weak cache
func (wc *WeakCache[K, V]) Load(key K) (*V, bool) {
wc.mutex.RLock()
entry, exists := wc.entries[key]
wc.mutex.RUnlock()
if !exists {
atomic.AddInt64(&wc.misses, 1)
return nil, false
}
// Get value from weak pointer
value := entry.weakPtr.Get()
if value == nil {
// Object was garbage collected
wc.remove(key)
atomic.AddInt64(&wc.misses, 1)
return nil, false
}
// Update access statistics
wc.mutex.Lock()
entry.lastAccess = time.Now()
atomic.AddInt64(&entry.hitCount, 1)
wc.mutex.Unlock()
atomic.AddInt64(&wc.hits, 1)
return value, true
}
// Remove entry from cache
func (wc *WeakCache[K, V]) remove(key K) {
wc.mutex.Lock()
defer wc.mutex.Unlock()
if entry, exists := wc.entries[key]; exists {
delete(wc.entries, key)
if wc.onEvict != nil && entry.weakPtr.IsValid() {
if value := entry.weakPtr.Get(); value != nil {
wc.onEvict(key, value)
}
}
}
}
// Evict oldest entry
func (wc *WeakCache[K, V]) evictOldest() {
var oldestKey K
var oldestTime time.Time
first := true
for key, entry := range wc.entries {
if first || entry.lastAccess.Before(oldestTime) {
oldestKey = key
oldestTime = entry.lastAccess
first = false
}
}
if !first {
wc.remove(oldestKey)
}
}
// Cleanup loop for expired entries
func (wc *WeakCache[K, V]) cleanupLoop() {
ticker := time.NewTicker(wc.ttl / 4)
defer ticker.Stop()
for range ticker.C {
now := time.Now()
wc.mutex.RLock()
var expired []K
for key, entry := range wc.entries {
if now.Sub(entry.lastAccess) > wc.ttl {
expired = append(expired, key)
}
}
wc.mutex.RUnlock()
for _, key := range expired {
wc.remove(key)
}
}
}
// Get cache statistics
func (wc *WeakCache[K, V]) Stats() CacheStats {
wc.mutex.RLock()
defer wc.mutex.RUnlock()
return CacheStats{
Size: len(wc.entries),
Hits: atomic.LoadInt64(&wc.hits),
Misses: atomic.LoadInt64(&wc.misses),
HitRatio: float64(wc.hits) / float64(wc.hits + wc.misses),
}
}
type CacheStats struct {
Size int
Hits int64
Misses int64
HitRatio float64
}
// Weak reference observer pattern
type WeakObserver[T any] struct {
observers map[uintptr]*WeakPointer[Observer[T]]
mutex sync.RWMutex
}
type Observer[T any] interface {
OnNext(value T)
OnError(err error)
OnComplete()
}
// Create new weak observer
func NewWeakObserver[T any]() *WeakObserver[T] {
return &WeakObserver[T]{
observers: make(map[uintptr]*WeakPointer[Observer[T]]),
}
}
// Subscribe observer
func (wo *WeakObserver[T]) Subscribe(observer Observer[T]) {
wo.mutex.Lock()
defer wo.mutex.Unlock()
weakObs := NewWeakPointer(&observer)
if weakObs != nil {
wo.observers[weakObs.id] = weakObs
// Set cleanup to remove from observers
weakObs.SetCleanup(func() {
wo.mutex.Lock()
delete(wo.observers, weakObs.id)
wo.mutex.Unlock()
})
}
}
// Notify all observers
func (wo *WeakObserver[T]) Notify(value T) {
wo.mutex.RLock()
defer wo.mutex.RUnlock()
for _, weakObs := range wo.observers {
if obs := weakObs.Get(); obs != nil {
(*obs).OnNext(value)
}
}
}
// Utility functions
func getCallerInfo() string {
_, file, line, ok := runtime.Caller(2)
if !ok {
return "unknown"
}
return fmt.Sprintf("%s:%d", file, line)
}
// Initialize global registry cleanup
func init() {
go func() {
for entry := range globalRegistry.cleanup {
globalRegistry.cleanupEntry(entry)
}
}()
}
This comprehensive guide covers enterprise Go memory management with advanced weak pointer implementation, memory pooling, GC optimization, and performance monitoring. Would you like me to continue with the remaining sections covering arena allocation, escape analysis optimization, and production deployment strategies?