package entity import ( "fmt" "math/rand" "testing" "time" ) // BenchmarkEntityCreation measures entity creation performance func BenchmarkEntityCreation(b *testing.B) { b.RunParallel(func(pb *testing.PB) { for pb.Next() { entity := NewEntity() _ = entity } }) } // BenchmarkEntityCombatState measures combat state operations func BenchmarkEntityCombatState(b *testing.B) { entity := NewEntity() b.Run("Sequential", func(b *testing.B) { for i := 0; i < b.N; i++ { entity.SetInCombat(true) _ = entity.IsInCombat() entity.SetInCombat(false) } }) b.Run("Parallel", func(b *testing.B) { b.RunParallel(func(pb *testing.PB) { for pb.Next() { entity.SetInCombat(true) _ = entity.IsInCombat() entity.SetInCombat(false) } }) }) } // BenchmarkEntityCastingState measures casting state operations func BenchmarkEntityCastingState(b *testing.B) { entity := NewEntity() b.Run("Sequential", func(b *testing.B) { for i := 0; i < b.N; i++ { entity.SetCasting(true) _ = entity.IsCasting() entity.SetCasting(false) } }) b.Run("Parallel", func(b *testing.B) { b.RunParallel(func(pb *testing.PB) { for pb.Next() { entity.SetCasting(true) _ = entity.IsCasting() entity.SetCasting(false) } }) }) } // BenchmarkEntityStatCalculations measures stat calculation performance func BenchmarkEntityStatCalculations(b *testing.B) { entity := NewEntity() info := entity.GetInfoStruct() // Set up some base stats info.SetStr(100.0) info.SetSta(100.0) info.SetAgi(100.0) info.SetWis(100.0) info.SetIntel(100.0) b.Run("GetStats", func(b *testing.B) { for i := 0; i < b.N; i++ { _ = entity.GetStr() _ = entity.GetSta() _ = entity.GetAgi() _ = entity.GetWis() _ = entity.GetIntel() } }) b.Run("GetStatsParallel", func(b *testing.B) { b.RunParallel(func(pb *testing.PB) { for pb.Next() { _ = entity.GetStr() _ = entity.GetSta() _ = entity.GetAgi() _ = entity.GetWis() _ = entity.GetIntel() } }) }) b.Run("GetPrimaryStat", func(b *testing.B) { for i := 0; i < b.N; i++ { _ = entity.GetPrimaryStat() } }) b.Run("CalculateBonuses", func(b *testing.B) { for i := 0; i < b.N; i++ { entity.CalculateBonuses() } }) } // BenchmarkEntitySpellEffects measures spell effect operations func BenchmarkEntitySpellEffects(b *testing.B) { entity := NewEntity() b.Run("AddRemoveSpellEffect", func(b *testing.B) { for i := 0; i < b.N; i++ { spellID := int32(i + 1000) entity.AddSpellEffect(spellID, 123, 30.0) entity.RemoveSpellEffect(spellID) } }) b.Run("AddRemoveSpellEffectParallel", func(b *testing.B) { var counter int64 b.RunParallel(func(pb *testing.PB) { for pb.Next() { spellID := int32(counter + 1000) counter++ entity.AddSpellEffect(spellID, 123, 30.0) entity.RemoveSpellEffect(spellID) } }) }) } // BenchmarkEntityMaintainedSpells measures maintained spell operations func BenchmarkEntityMaintainedSpells(b *testing.B) { entity := NewEntity() info := entity.GetInfoStruct() info.SetMaxConcentration(1000) // Large pool for benchmarking b.Run("AddRemoveMaintainedSpell", func(b *testing.B) { for i := 0; i < b.N; i++ { spellID := int32(i + 2000) if entity.AddMaintainedSpell("Benchmark Spell", spellID, 60.0, 1) { entity.RemoveMaintainedSpell(spellID) } } }) b.Run("AddRemoveMaintainedSpellParallel", func(b *testing.B) { var counter int64 b.RunParallel(func(pb *testing.PB) { for pb.Next() { spellID := int32(counter + 2000) counter++ if entity.AddMaintainedSpell("Benchmark Spell", spellID, 60.0, 1) { entity.RemoveMaintainedSpell(spellID) } } }) }) } // BenchmarkInfoStructBasicOps measures basic InfoStruct operations func BenchmarkInfoStructBasicOps(b *testing.B) { info := NewInfoStruct() b.Run("SetGetName", func(b *testing.B) { for i := 0; i < b.N; i++ { info.SetName("BenchmarkCharacter") _ = info.GetName() } }) b.Run("SetGetNameParallel", func(b *testing.B) { b.RunParallel(func(pb *testing.PB) { for pb.Next() { info.SetName("BenchmarkCharacter") _ = info.GetName() } }) }) b.Run("SetGetLevel", func(b *testing.B) { for i := 0; i < b.N; i++ { info.SetLevel(int16(i % 100)) _ = info.GetLevel() } }) b.Run("SetGetStats", func(b *testing.B) { for i := 0; i < b.N; i++ { val := float32(i % 1000) info.SetStr(val) info.SetSta(val) info.SetAgi(val) info.SetWis(val) info.SetIntel(val) _ = info.GetStr() _ = info.GetSta() _ = info.GetAgi() _ = info.GetWis() _ = info.GetIntel() } }) } // BenchmarkInfoStructConcentration measures concentration operations func BenchmarkInfoStructConcentration(b *testing.B) { info := NewInfoStruct() info.SetMaxConcentration(1000) b.Run("AddRemoveConcentration", func(b *testing.B) { for i := 0; i < b.N; i++ { amount := int16(i%10 + 1) if info.AddConcentration(amount) { info.RemoveConcentration(amount) } } }) b.Run("AddRemoveConcentrationParallel", func(b *testing.B) { b.RunParallel(func(pb *testing.PB) { for pb.Next() { amount := int16(1) // Use small amount to reduce contention if info.AddConcentration(amount) { info.RemoveConcentration(amount) } } }) }) } // BenchmarkInfoStructCoins measures coin operations func BenchmarkInfoStructCoins(b *testing.B) { info := NewInfoStruct() b.Run("AddRemoveCoins", func(b *testing.B) { for i := 0; i < b.N; i++ { amount := int32(i%10000 + 1) info.AddCoins(amount) info.RemoveCoins(amount / 2) } }) b.Run("AddRemoveCoinsParallel", func(b *testing.B) { b.RunParallel(func(pb *testing.PB) { for pb.Next() { amount := int32(100) info.AddCoins(amount) info.RemoveCoins(amount / 2) } }) }) b.Run("GetCoins", func(b *testing.B) { for i := 0; i < b.N; i++ { _ = info.GetCoins() } }) } // BenchmarkInfoStructResistances measures resistance operations func BenchmarkInfoStructResistances(b *testing.B) { info := NewInfoStruct() resistTypes := []string{"heat", "cold", "magic", "mental", "divine", "disease", "poison"} b.Run("SetGetResistances", func(b *testing.B) { for i := 0; i < b.N; i++ { resistType := resistTypes[i%len(resistTypes)] value := int16(i % 100) info.SetResistance(resistType, value) _ = info.GetResistance(resistType) } }) b.Run("SetGetResistancesParallel", func(b *testing.B) { b.RunParallel(func(pb *testing.PB) { for pb.Next() { resistType := resistTypes[rand.Intn(len(resistTypes))] value := int16(rand.Intn(100)) info.SetResistance(resistType, value) _ = info.GetResistance(resistType) } }) }) } // BenchmarkInfoStructClone measures clone operations func BenchmarkInfoStructClone(b *testing.B) { info := NewInfoStruct() // Set up some state to clone info.SetName("Original Character") info.SetLevel(50) info.SetStr(100.0) info.SetSta(120.0) info.SetAgi(90.0) info.SetWis(110.0) info.SetIntel(105.0) info.AddConcentration(5) info.AddCoins(50000) b.ResetTimer() for i := 0; i < b.N; i++ { clone := info.Clone() _ = clone } } // BenchmarkEntityPetManagement measures pet management operations func BenchmarkEntityPetManagement(b *testing.B) { entity := NewEntity() b.Run("SetGetPet", func(b *testing.B) { for i := 0; i < b.N; i++ { pet := NewEntity() entity.SetPet(pet) _ = entity.GetPet() entity.SetPet(nil) } }) b.Run("SetGetPetParallel", func(b *testing.B) { b.RunParallel(func(pb *testing.PB) { for pb.Next() { pet := NewEntity() entity.SetPet(pet) _ = entity.GetPet() entity.SetPet(nil) } }) }) b.Run("AllPetTypes", func(b *testing.B) { for i := 0; i < b.N; i++ { pet := NewEntity() entity.SetPet(pet) _ = entity.GetPet() entity.SetCharmedPet(pet) _ = entity.GetCharmedPet() entity.SetDeityPet(pet) _ = entity.GetDeityPet() entity.SetCosmeticPet(pet) _ = entity.GetCosmeticPet() // Clear all pets entity.SetPet(nil) entity.SetCharmedPet(nil) entity.SetDeityPet(nil) entity.SetCosmeticPet(nil) } }) } // BenchmarkConcurrentWorkload simulates a realistic concurrent workload func BenchmarkConcurrentWorkload(b *testing.B) { numEntities := 100 entities := make([]*Entity, numEntities) // Create entities for i := 0; i < numEntities; i++ { entities[i] = NewEntity() info := entities[i].GetInfoStruct() info.SetMaxConcentration(50) info.SetName("Entity" + string(rune('A'+i%26))) info.SetLevel(int16(i%100 + 1)) } b.ResetTimer() b.Run("MixedOperations", func(b *testing.B) { b.RunParallel(func(pb *testing.PB) { for pb.Next() { entityIdx := rand.Intn(numEntities) entity := entities[entityIdx] switch rand.Intn(10) { case 0, 1: // Combat state changes (20%) entity.SetInCombat(rand.Intn(2) == 1) _ = entity.IsInCombat() case 2, 3: // Stat reads (20%) _ = entity.GetStr() _ = entity.GetSta() _ = entity.GetPrimaryStat() case 4: // Spell effects (10%) spellID := int32(rand.Intn(1000) + 10000) entity.AddSpellEffect(spellID, int32(entityIdx), 30.0) entity.RemoveSpellEffect(spellID) case 5: // Maintained spells (10%) spellID := int32(rand.Intn(100) + 20000) if entity.AddMaintainedSpell("Workload Spell", spellID, 60.0, 1) { entity.RemoveMaintainedSpell(spellID) } case 6, 7: // InfoStruct operations (20%) info := entity.GetInfoStruct() info.SetStr(float32(rand.Intn(200) + 50)) _ = info.GetStr() case 8: // Coin operations (10%) info := entity.GetInfoStruct() info.AddCoins(int32(rand.Intn(1000))) _ = info.GetCoins() case 9: // Resistance operations (10%) info := entity.GetInfoStruct() resistTypes := []string{"heat", "cold", "magic", "mental"} resistType := resistTypes[rand.Intn(len(resistTypes))] info.SetResistance(resistType, int16(rand.Intn(100))) _ = info.GetResistance(resistType) } } }) }) } // BenchmarkMemoryAllocation measures memory allocation patterns func BenchmarkMemoryAllocation(b *testing.B) { b.Run("EntityAllocation", func(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { entity := NewEntity() _ = entity } }) b.Run("InfoStructAllocation", func(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { info := NewInfoStruct() _ = info } }) b.Run("CloneAllocation", func(b *testing.B) { info := NewInfoStruct() info.SetName("Test") info.SetLevel(50) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { clone := info.Clone() _ = clone } }) } // BenchmarkContention measures performance under high contention func BenchmarkContention(b *testing.B) { entity := NewEntity() info := entity.GetInfoStruct() info.SetMaxConcentration(10) // Low limit to create contention b.Run("HighContentionConcentration", func(b *testing.B) { b.RunParallel(func(pb *testing.PB) { for pb.Next() { if info.AddConcentration(1) { // Hold for a brief moment to increase contention time.Sleep(time.Nanosecond) info.RemoveConcentration(1) } } }) }) b.Run("HighContentionSpellEffects", func(b *testing.B) { var spellCounter int64 b.RunParallel(func(pb *testing.PB) { for pb.Next() { spellID := int32(spellCounter % 100) // Reuse spell IDs to create contention spellCounter++ entity.AddSpellEffect(spellID, 123, 30.0) entity.RemoveSpellEffect(spellID) } }) }) } // BenchmarkScalability tests performance as load increases func BenchmarkScalability(b *testing.B) { goroutineCounts := []int{1, 2, 4, 8, 16, 32, 64} for _, numGoroutines := range goroutineCounts { b.Run(fmt.Sprintf("Goroutines_%d", numGoroutines), func(b *testing.B) { entity := NewEntity() b.RunParallel(func(pb *testing.PB) { for pb.Next() { entity.SetInCombat(true) _ = entity.IsInCombat() entity.SetInCombat(false) } }) }) } }