eq2go/internal/factions/benchmark_test.go

546 lines
12 KiB
Go

package factions
import (
"testing"
)
// Benchmark MasterFactionList operations
func BenchmarkMasterFactionList(b *testing.B) {
b.Run("GetFaction", func(b *testing.B) {
mfl := NewMasterList()
// Pre-populate with factions
for i := int32(1); i <= 1000; i++ {
faction := NewFaction(i, "Benchmark Faction", "Test", "Benchmark test")
mfl.AddFaction(faction)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
factionID := int32((i % 1000) + 1)
_ = mfl.GetFaction(factionID)
}
})
b.Run("GetFactionByName", func(b *testing.B) {
mfl := NewMasterList()
// Pre-populate with factions
for i := int32(1); i <= 1000; i++ {
faction := NewFaction(i, "Benchmark Faction", "Test", "Benchmark test")
mfl.AddFaction(faction)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = mfl.GetFactionByName("Benchmark Faction")
}
})
b.Run("AddFaction", func(b *testing.B) {
mfl := NewMasterList()
// Pre-populate with factions
for i := int32(1); i <= 1000; i++ {
faction := NewFaction(i, "Benchmark Faction", "Test", "Benchmark test")
mfl.AddFaction(faction)
}
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) {
mfl := NewMasterList()
// Pre-populate with factions
for i := int32(1); i <= 1000; i++ {
faction := NewFaction(i, "Benchmark Faction", "Test", "Benchmark test")
mfl.AddFaction(faction)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = mfl.GetFactionCount()
}
})
b.Run("AddHostileFaction", func(b *testing.B) {
mfl := NewMasterList()
// Pre-populate with factions
for i := int32(1); i <= 1000; i++ {
faction := NewFaction(i, "Benchmark Faction", "Test", "Benchmark test")
mfl.AddFaction(faction)
}
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) {
mfl := NewMasterList()
// Pre-populate with factions and some hostile relationships
for i := int32(1); i <= 1000; i++ {
faction := NewFaction(i, "Benchmark Faction", "Test", "Benchmark test")
mfl.AddFaction(faction)
}
// Add a reasonable number of hostile relationships
for i := int32(1); i <= 100; i++ {
for j := int32(1); j <= 5; j++ {
mfl.AddHostileFaction(i, i+j)
}
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
factionID := int32((i % 100) + 1)
_ = mfl.GetHostileFactions(factionID)
}
})
b.Run("ValidateFactions", func(b *testing.B) {
mfl := NewMasterList()
// Pre-populate with factions
for i := int32(1); i <= 1000; i++ {
faction := NewFaction(i, "Benchmark Faction", "Test", "Benchmark test")
mfl.AddFaction(faction)
}
// Add some hostile relationships for realistic validation
for i := int32(1); i <= 100; i++ {
mfl.AddHostileFaction(i, i+1)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = mfl.ValidateFactions()
}
})
}
// Benchmark PlayerFaction operations
func BenchmarkPlayerFaction(b *testing.B) {
mfl := NewMasterList()
// 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()
for i := 0; i < b.N; i++ {
_ = manager.ValidateAllFactions()
}
})
}
// 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 := NewMasterList()
// 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 := NewMasterList()
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++ {
_ = NewMasterList()
}
})
b.Run("PlayerFactionCreation", func(b *testing.B) {
mfl := NewMasterList()
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 := NewMasterList()
// 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 := NewMasterList()
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 := NewMasterList()
// 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 := NewMasterList()
// 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)
}
})
}
}