Skip to main content
Glama
atomic_benchmark_test.go6.12 kB
package process import ( "sync" "sync/atomic" "testing" "time" "unsafe" ) // BenchmarkAtomicStateRead tests the performance of atomic state reads func BenchmarkAtomicStateRead(b *testing.B) { // Create a process with atomic state p := &Process{ ID: "test-123", Name: "test-process", Script: "test", Status: StatusRunning, StartTime: time.Now(), } // Initialize atomic state initialState := ProcessState{ ID: p.ID, Name: p.Name, Script: p.Script, Status: p.Status, StartTime: p.StartTime, } atomic.StorePointer(&p.atomicState, unsafe.Pointer(&initialState)) b.ResetTimer() for i := 0; i < b.N; i++ { state := p.GetStateAtomic() _ = state.Status // Prevent compiler optimization } } // BenchmarkMutexRead tests the performance of mutex-based reads (baseline) func BenchmarkMutexRead(b *testing.B) { p := &Process{ ID: "test-123", Name: "test-process", Script: "test", Status: StatusRunning, StartTime: time.Now(), mu: sync.RWMutex{}, } b.ResetTimer() for i := 0; i < b.N; i++ { p.mu.RLock() status := p.Status p.mu.RUnlock() _ = status // Prevent compiler optimization } } // BenchmarkConcurrentAtomicReads tests concurrent atomic reads func BenchmarkConcurrentAtomicReads(b *testing.B) { p := &Process{ ID: "test-123", Name: "test-process", Script: "test", Status: StatusRunning, StartTime: time.Now(), } // Initialize atomic state initialState := ProcessState{ ID: p.ID, Name: p.Name, Script: p.Script, Status: p.Status, StartTime: p.StartTime, } atomic.StorePointer(&p.atomicState, unsafe.Pointer(&initialState)) b.RunParallel(func(pb *testing.PB) { for pb.Next() { state := p.GetStateAtomic() _ = state.Status } }) } // BenchmarkConcurrentMutexReads tests concurrent mutex reads (baseline) func BenchmarkConcurrentMutexReads(b *testing.B) { p := &Process{ ID: "test-123", Name: "test-process", Script: "test", Status: StatusRunning, StartTime: time.Now(), mu: sync.RWMutex{}, } b.RunParallel(func(pb *testing.PB) { for pb.Next() { p.mu.RLock() status := p.Status p.mu.RUnlock() _ = status } }) } // BenchmarkAtomicStateUpdate tests the performance of atomic state updates func BenchmarkAtomicStateUpdate(b *testing.B) { p := &Process{ ID: "test-123", Name: "test-process", Script: "test", Status: StatusRunning, StartTime: time.Now(), } // Initialize atomic state initialState := ProcessState{ ID: p.ID, Name: p.Name, Script: p.Script, Status: p.Status, StartTime: p.StartTime, } atomic.StorePointer(&p.atomicState, unsafe.Pointer(&initialState)) b.ResetTimer() for i := 0; i < b.N; i++ { p.UpdateStateAtomic(func(state ProcessState) ProcessState { return state.CopyWithStatus(StatusStopped) }) } } // BenchmarkMutexUpdate tests the performance of mutex-based updates (baseline) func BenchmarkMutexUpdate(b *testing.B) { p := &Process{ ID: "test-123", Name: "test-process", Script: "test", Status: StatusRunning, StartTime: time.Now(), mu: sync.RWMutex{}, } b.ResetTimer() for i := 0; i < b.N; i++ { p.mu.Lock() p.Status = StatusStopped p.mu.Unlock() } } // BenchmarkFullStateAccess tests reading all fields atomically func BenchmarkFullStateAccess(b *testing.B) { p := &Process{ ID: "test-123", Name: "test-process", Script: "test", Status: StatusRunning, StartTime: time.Now(), } // Initialize atomic state with all fields exitCode := 0 endTime := time.Now() initialState := ProcessState{ ID: p.ID, Name: p.Name, Script: p.Script, Status: StatusSuccess, StartTime: p.StartTime, EndTime: &endTime, ExitCode: &exitCode, Command: "node", Args: []string{"index.js"}, Env: []string{"NODE_ENV=production"}, Dir: "/app", } atomic.StorePointer(&p.atomicState, unsafe.Pointer(&initialState)) b.ResetTimer() for i := 0; i < b.N; i++ { state := p.GetStateAtomic() // Access multiple fields to simulate real usage _ = state.Status _ = state.StartTime _ = state.EndTime _ = state.ExitCode _ = state.Name } } // BenchmarkAtomicMemoryAllocation tests allocation behavior func BenchmarkAtomicMemoryAllocation(b *testing.B) { p := &Process{ ID: "test-123", Name: "test-process", Script: "test", Status: StatusRunning, StartTime: time.Now(), } // Initialize atomic state initialState := ProcessState{ ID: p.ID, Name: p.Name, Script: p.Script, Status: p.Status, StartTime: p.StartTime, } atomic.StorePointer(&p.atomicState, unsafe.Pointer(&initialState)) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { state := p.GetStateAtomic() _ = state.Status } } // BenchmarkCASRetries tests performance under contention func BenchmarkCASRetries(b *testing.B) { p := &Process{ ID: "test-123", Name: "test-process", Script: "test", Status: StatusRunning, StartTime: time.Now(), } // Initialize atomic state initialState := ProcessState{ ID: p.ID, Name: p.Name, Script: p.Script, Status: p.Status, StartTime: p.StartTime, } atomic.StorePointer(&p.atomicState, unsafe.Pointer(&initialState)) // Simulate high contention with concurrent updates var wg sync.WaitGroup stop := make(chan struct{}) // Start background updaters for i := 0; i < 4; i++ { wg.Add(1) go func() { defer wg.Done() for { select { case <-stop: return default: p.UpdateStateAtomic(func(state ProcessState) ProcessState { if state.Status == StatusRunning { return state.CopyWithStatus(StatusStopped) } return state.CopyWithStatus(StatusRunning) }) } } }() } b.ResetTimer() for i := 0; i < b.N; i++ { p.UpdateStateAtomic(func(state ProcessState) ProcessState { return state.CopyWithStatus(StatusSuccess) }) } close(stop) wg.Wait() }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/standardbeagle/brummer'

If you have feedback or need assistance with the MCP directory API, please join our Discord server