508 lines
12 KiB
Go
508 lines
12 KiB
Go
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)
|
|
}
|
|
})
|
|
}
|
|
} |