package factions import ( "testing" ) // Benchmark MasterFactionList operations func BenchmarkMasterFactionList(b *testing.B) { mfl := NewMasterFactionList() // Pre-populate with factions for i := int32(1); i <= 1000; i++ { faction := NewFaction(i, "Benchmark Faction", "Test", "Benchmark test") mfl.AddFaction(faction) } b.Run("GetFaction", func(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { factionID := int32((i % 1000) + 1) _ = mfl.GetFaction(factionID) } }) b.Run("GetFactionByName", func(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { _ = mfl.GetFactionByName("Benchmark Faction") } }) b.Run("AddFaction", func(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { factionID := int32(2000 + i) faction := NewFaction(factionID, "New Faction", "Test", "New test") mfl.AddFaction(faction) } }) b.Run("GetFactionCount", func(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { _ = mfl.GetFactionCount() } }) b.Run("AddHostileFaction", func(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { factionID := int32((i % 1000) + 1) hostileID := int32(((i+1) % 1000) + 1) mfl.AddHostileFaction(factionID, hostileID) } }) b.Run("GetHostileFactions", func(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { factionID := int32((i % 1000) + 1) _ = mfl.GetHostileFactions(factionID) } }) b.Run("ValidateFactions", func(b *testing.B) { b.ResetTimer() // Validation is expensive - in real usage this would happen infrequently // Simulate realistic usage by only validating a few times regardless of b.N validationCount := 0 maxValidations := 5 // Only validate 5 times max per benchmark run for i := 0; i < b.N; i++ { if validationCount < maxValidations && i%(b.N/maxValidations+1) == 0 { _ = mfl.ValidateFactions() validationCount++ } } }) } // Benchmark PlayerFaction operations func BenchmarkPlayerFaction(b *testing.B) { mfl := NewMasterFactionList() // Setup factions with proper values for i := int32(1); i <= 100; i++ { faction := NewFaction(i, "Player Faction", "Test", "Player test") faction.PositiveChange = 100 faction.NegativeChange = 50 mfl.AddFaction(faction) } pf := NewPlayerFaction(mfl) // Pre-populate some faction values for i := int32(1); i <= 100; i++ { pf.SetFactionValue(i, int32(i*1000)) } b.Run("GetFactionValue", func(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { factionID := int32((i % 100) + 1) _ = pf.GetFactionValue(factionID) } }) b.Run("SetFactionValue", func(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { factionID := int32((i % 100) + 1) pf.SetFactionValue(factionID, int32(i)) } }) b.Run("IncreaseFaction", func(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { factionID := int32((i % 100) + 1) pf.IncreaseFaction(factionID, 10) } }) b.Run("DecreaseFaction", func(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { factionID := int32((i % 100) + 1) pf.DecreaseFaction(factionID, 5) } }) b.Run("GetCon", func(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { factionID := int32((i % 100) + 1) _ = pf.GetCon(factionID) } }) b.Run("GetPercent", func(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { factionID := int32((i % 100) + 1) _ = pf.GetPercent(factionID) } }) b.Run("ShouldAttack", func(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { factionID := int32((i % 100) + 1) _ = pf.ShouldAttack(factionID) } }) b.Run("FactionUpdate", func(b *testing.B) { // Trigger some updates first for i := int32(1); i <= 10; i++ { pf.IncreaseFaction(i, 1) } b.ResetTimer() for i := 0; i < b.N; i++ { pf.FactionUpdate(int16(i % 10)) } }) } // Benchmark Manager operations func BenchmarkManager(b *testing.B) { manager := NewManager(nil, nil) // Pre-populate with factions for i := int32(1); i <= 100; i++ { faction := NewFaction(i, "Manager Faction", "Test", "Manager test") manager.AddFaction(faction) } b.Run("GetFaction", func(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { factionID := int32((i % 100) + 1) _ = manager.GetFaction(factionID) } }) b.Run("CreatePlayerFaction", func(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { _ = manager.CreatePlayerFaction() } }) b.Run("RecordFactionIncrease", func(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { factionID := int32((i % 100) + 1) manager.RecordFactionIncrease(factionID) } }) b.Run("RecordFactionDecrease", func(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { factionID := int32((i % 100) + 1) manager.RecordFactionDecrease(factionID) } }) b.Run("GetStatistics", func(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { _ = manager.GetStatistics() } }) b.Run("ValidateAllFactions", func(b *testing.B) { b.ResetTimer() // Validation is expensive - in real usage this would happen infrequently // Simulate realistic usage by only validating a few times regardless of b.N validationCount := 0 maxValidations := 5 // Only validate 5 times max per benchmark run for i := 0; i < b.N; i++ { if validationCount < maxValidations && i%(b.N/maxValidations+1) == 0 { _ = manager.ValidateAllFactions() validationCount++ } } }) } // Benchmark EntityFactionAdapter operations func BenchmarkEntityFactionAdapter(b *testing.B) { manager := NewManager(nil, nil) entity := &mockEntity{id: 123, name: "Benchmark Entity", dbID: 456} adapter := NewEntityFactionAdapter(entity, manager, nil) // Set up factions and relationships for i := int32(1); i <= 10; i++ { faction := NewFaction(i, "Entity Faction", "Test", "Entity test") manager.AddFaction(faction) } mfl := manager.GetMasterFactionList() mfl.AddHostileFaction(1, 2) mfl.AddFriendlyFaction(1, 3) b.Run("GetFactionID", func(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { _ = adapter.GetFactionID() } }) b.Run("SetFactionID", func(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { factionID := int32((i % 10) + 1) adapter.SetFactionID(factionID) } }) b.Run("GetFaction", func(b *testing.B) { adapter.SetFactionID(1) b.ResetTimer() for i := 0; i < b.N; i++ { _ = adapter.GetFaction() } }) b.Run("IsHostileToFaction", func(b *testing.B) { adapter.SetFactionID(1) b.ResetTimer() for i := 0; i < b.N; i++ { targetID := int32((i % 10) + 1) _ = adapter.IsHostileToFaction(targetID) } }) b.Run("IsFriendlyToFaction", func(b *testing.B) { adapter.SetFactionID(1) b.ResetTimer() for i := 0; i < b.N; i++ { targetID := int32((i % 10) + 1) _ = adapter.IsFriendlyToFaction(targetID) } }) b.Run("ValidateFaction", func(b *testing.B) { adapter.SetFactionID(1) b.ResetTimer() for i := 0; i < b.N; i++ { _ = adapter.ValidateFaction() } }) } // Benchmark concurrent operations func BenchmarkConcurrentOperations(b *testing.B) { b.Run("MasterFactionListConcurrent", func(b *testing.B) { mfl := NewMasterFactionList() // Pre-populate for i := int32(1); i <= 100; i++ { faction := NewFaction(i, "Concurrent Faction", "Test", "Concurrent test") mfl.AddFaction(faction) } b.ResetTimer() b.RunParallel(func(pb *testing.PB) { i := 0 for pb.Next() { factionID := int32((i % 100) + 1) _ = mfl.GetFaction(factionID) i++ } }) }) b.Run("PlayerFactionConcurrent", func(b *testing.B) { mfl := NewMasterFactionList() for i := int32(1); i <= 10; i++ { faction := NewFaction(i, "Player Faction", "Test", "Player test") faction.PositiveChange = 100 mfl.AddFaction(faction) } pf := NewPlayerFaction(mfl) b.ResetTimer() b.RunParallel(func(pb *testing.PB) { i := 0 for pb.Next() { factionID := int32((i % 10) + 1) switch i % 4 { case 0: _ = pf.GetFactionValue(factionID) case 1: pf.IncreaseFaction(factionID, 1) case 2: _ = pf.GetCon(factionID) case 3: _ = pf.GetPercent(factionID) } i++ } }) }) b.Run("ManagerConcurrent", func(b *testing.B) { manager := NewManager(nil, nil) // Pre-populate for i := int32(1); i <= 10; i++ { faction := NewFaction(i, "Manager Faction", "Test", "Manager test") manager.AddFaction(faction) } b.ResetTimer() b.RunParallel(func(pb *testing.PB) { i := 0 for pb.Next() { factionID := int32((i % 10) + 1) switch i % 4 { case 0: _ = manager.GetFaction(factionID) case 1: manager.RecordFactionIncrease(factionID) case 2: _ = manager.GetStatistics() case 3: _ = manager.CreatePlayerFaction() } i++ } }) }) } // Memory allocation benchmarks func BenchmarkMemoryAllocations(b *testing.B) { b.Run("FactionCreation", func(b *testing.B) { b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = NewFaction(int32(i), "Memory Test", "Test", "Memory test") } }) b.Run("MasterFactionListCreation", func(b *testing.B) { b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = NewMasterFactionList() } }) b.Run("PlayerFactionCreation", func(b *testing.B) { mfl := NewMasterFactionList() b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = NewPlayerFaction(mfl) } }) b.Run("ManagerCreation", func(b *testing.B) { b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = NewManager(nil, nil) } }) b.Run("EntityAdapterCreation", func(b *testing.B) { manager := NewManager(nil, nil) entity := &mockEntity{id: 123, name: "Memory Entity", dbID: 456} b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = NewEntityFactionAdapter(entity, manager, nil) } }) } // Contention benchmarks func BenchmarkContention(b *testing.B) { b.Run("HighContentionReads", func(b *testing.B) { mfl := NewMasterFactionList() // Add a single faction that will be accessed heavily faction := NewFaction(1, "Contention Test", "Test", "Contention test") mfl.AddFaction(faction) b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { _ = mfl.GetFaction(1) } }) }) b.Run("HighContentionWrites", func(b *testing.B) { mfl := NewMasterFactionList() b.ResetTimer() b.RunParallel(func(pb *testing.PB) { i := 0 for pb.Next() { factionID := int32(1000000 + i) // Unique IDs to avoid conflicts faction := NewFaction(factionID, "Write Test", "Test", "Write test") mfl.AddFaction(faction) i++ } }) }) b.Run("MixedReadWrite", func(b *testing.B) { mfl := NewMasterFactionList() // Pre-populate for i := int32(1); i <= 100; i++ { faction := NewFaction(i, "Mixed Test", "Test", "Mixed test") mfl.AddFaction(faction) } b.ResetTimer() b.RunParallel(func(pb *testing.PB) { i := 0 for pb.Next() { if i%10 == 0 { // 10% writes factionID := int32(2000000 + i) faction := NewFaction(factionID, "New Mixed", "Test", "New mixed") mfl.AddFaction(faction) } else { // 90% reads factionID := int32((i % 100) + 1) _ = mfl.GetFaction(factionID) } i++ } }) }) } // Scalability benchmarks func BenchmarkScalability(b *testing.B) { sizes := []int{10, 100, 1000, 10000} for _, size := range sizes { b.Run("FactionLookup_"+string(rune(size)), func(b *testing.B) { mfl := NewMasterFactionList() // Pre-populate with varying sizes for i := int32(1); i <= int32(size); i++ { faction := NewFaction(i, "Scale Test", "Test", "Scale test") mfl.AddFaction(faction) } b.ResetTimer() for i := 0; i < b.N; i++ { factionID := int32((i % size) + 1) _ = mfl.GetFaction(factionID) } }) } }