563 lines
12 KiB
Go
563 lines
12 KiB
Go
package ground_spawn
|
|
|
|
import (
|
|
"testing"
|
|
)
|
|
|
|
// Mock implementations are in test_utils.go
|
|
|
|
// Benchmark GroundSpawn operations
|
|
func BenchmarkGroundSpawn(b *testing.B) {
|
|
config := GroundSpawnConfig{
|
|
GroundSpawnID: 1,
|
|
CollectionSkill: SkillGathering,
|
|
NumberHarvests: 10,
|
|
AttemptsPerHarvest: 2,
|
|
RandomizeHeading: true,
|
|
Location: SpawnLocation{
|
|
X: 100.0, Y: 200.0, Z: 300.0, Heading: 45.0, GridID: 1,
|
|
},
|
|
Name: "Benchmark Node",
|
|
Description: "A benchmark harvestable node",
|
|
}
|
|
|
|
gs := NewGroundSpawn(config)
|
|
|
|
b.Run("GetNumberHarvests", func(b *testing.B) {
|
|
for b.Loop() {
|
|
_ = gs.GetNumberHarvests()
|
|
}
|
|
})
|
|
|
|
b.Run("SetNumberHarvests", func(b *testing.B) {
|
|
b.ResetTimer()
|
|
for i := 0; b.Loop(); i++ {
|
|
gs.SetNumberHarvests(int8(i % 10))
|
|
}
|
|
})
|
|
|
|
b.Run("GetCollectionSkill", func(b *testing.B) {
|
|
b.ResetTimer()
|
|
for b.Loop() {
|
|
_ = gs.GetCollectionSkill()
|
|
}
|
|
})
|
|
|
|
b.Run("SetCollectionSkill", func(b *testing.B) {
|
|
skills := []string{SkillGathering, SkillMining, SkillFishing, SkillTrapping}
|
|
b.ResetTimer()
|
|
for i := 0; b.Loop(); i++ {
|
|
gs.SetCollectionSkill(skills[i%len(skills)])
|
|
}
|
|
})
|
|
|
|
b.Run("IsAvailable", func(b *testing.B) {
|
|
b.ResetTimer()
|
|
for b.Loop() {
|
|
_ = gs.IsAvailable()
|
|
}
|
|
})
|
|
|
|
b.Run("IsDepleted", func(b *testing.B) {
|
|
b.ResetTimer()
|
|
for b.Loop() {
|
|
_ = gs.IsDepleted()
|
|
}
|
|
})
|
|
|
|
b.Run("GetHarvestMessageName", func(b *testing.B) {
|
|
b.ResetTimer()
|
|
for i := 0; b.Loop(); i++ {
|
|
_ = gs.GetHarvestMessageName(i%2 == 0, i%4 == 0)
|
|
}
|
|
})
|
|
|
|
b.Run("GetHarvestSpellType", func(b *testing.B) {
|
|
b.ResetTimer()
|
|
for b.Loop() {
|
|
_ = gs.GetHarvestSpellType()
|
|
}
|
|
})
|
|
|
|
b.Run("Copy", func(b *testing.B) {
|
|
b.ResetTimer()
|
|
for b.Loop() {
|
|
copy := gs.Copy()
|
|
_ = copy
|
|
}
|
|
})
|
|
|
|
b.Run("Respawn", func(b *testing.B) {
|
|
b.ResetTimer()
|
|
for b.Loop() {
|
|
gs.Respawn()
|
|
}
|
|
})
|
|
}
|
|
|
|
// Benchmark Manager operations
|
|
func BenchmarkManager(b *testing.B) {
|
|
manager := NewManager(nil, &mockLogger{})
|
|
|
|
// Pre-populate with ground spawns
|
|
for i := int32(1); i <= 100; i++ {
|
|
config := GroundSpawnConfig{
|
|
GroundSpawnID: i,
|
|
CollectionSkill: SkillGathering,
|
|
NumberHarvests: 5,
|
|
AttemptsPerHarvest: 1,
|
|
Location: SpawnLocation{
|
|
X: float32(i * 10), Y: float32(i * 20), Z: float32(i * 30),
|
|
Heading: float32(i * 45), GridID: 1,
|
|
},
|
|
Name: "Benchmark Node",
|
|
Description: "Benchmark node",
|
|
}
|
|
gs := manager.CreateGroundSpawn(config)
|
|
_ = gs
|
|
}
|
|
|
|
b.Run("GetGroundSpawn", func(b *testing.B) {
|
|
b.ResetTimer()
|
|
for i := 0; b.Loop(); i++ {
|
|
spawnID := int32((i % 100) + 1)
|
|
_ = manager.GetGroundSpawn(spawnID)
|
|
}
|
|
})
|
|
|
|
b.Run("CreateGroundSpawn", func(b *testing.B) {
|
|
b.ResetTimer()
|
|
for i := 0; b.Loop(); i++ {
|
|
config := GroundSpawnConfig{
|
|
GroundSpawnID: int32(2000 + i),
|
|
CollectionSkill: SkillMining,
|
|
NumberHarvests: 3,
|
|
AttemptsPerHarvest: 1,
|
|
Location: SpawnLocation{
|
|
X: float32(i), Y: float32(i * 2), Z: float32(i * 3),
|
|
Heading: 0, GridID: 1,
|
|
},
|
|
Name: "New Node",
|
|
Description: "New benchmark node",
|
|
}
|
|
_ = manager.CreateGroundSpawn(config)
|
|
}
|
|
})
|
|
|
|
b.Run("GetGroundSpawnsByZone", func(b *testing.B) {
|
|
b.ResetTimer()
|
|
for b.Loop() {
|
|
_ = manager.GetGroundSpawnsByZone(1)
|
|
}
|
|
})
|
|
|
|
b.Run("GetGroundSpawnCount", func(b *testing.B) {
|
|
b.ResetTimer()
|
|
for b.Loop() {
|
|
_ = manager.GetGroundSpawnCount()
|
|
}
|
|
})
|
|
|
|
b.Run("GetActiveGroundSpawns", func(b *testing.B) {
|
|
b.ResetTimer()
|
|
for b.Loop() {
|
|
_ = manager.GetActiveGroundSpawns()
|
|
}
|
|
})
|
|
|
|
b.Run("GetDepletedGroundSpawns", func(b *testing.B) {
|
|
b.ResetTimer()
|
|
for b.Loop() {
|
|
_ = manager.GetDepletedGroundSpawns()
|
|
}
|
|
})
|
|
|
|
b.Run("GetStatistics", func(b *testing.B) {
|
|
b.ResetTimer()
|
|
for b.Loop() {
|
|
_ = manager.GetStatistics()
|
|
}
|
|
})
|
|
|
|
b.Run("ResetStatistics", func(b *testing.B) {
|
|
b.ResetTimer()
|
|
for b.Loop() {
|
|
manager.ResetStatistics()
|
|
}
|
|
})
|
|
|
|
b.Run("ProcessRespawns", func(b *testing.B) {
|
|
b.ResetTimer()
|
|
for b.Loop() {
|
|
manager.ProcessRespawns()
|
|
}
|
|
})
|
|
}
|
|
|
|
// Benchmark concurrent operations
|
|
func BenchmarkConcurrentOperations(b *testing.B) {
|
|
b.Run("GroundSpawnConcurrentReads", func(b *testing.B) {
|
|
config := GroundSpawnConfig{
|
|
GroundSpawnID: 1,
|
|
CollectionSkill: SkillGathering,
|
|
NumberHarvests: 10,
|
|
AttemptsPerHarvest: 1,
|
|
Location: SpawnLocation{
|
|
X: 100, Y: 200, Z: 300, Heading: 45, GridID: 1,
|
|
},
|
|
Name: "Concurrent Node",
|
|
Description: "Concurrent benchmark node",
|
|
}
|
|
gs := NewGroundSpawn(config)
|
|
|
|
b.ResetTimer()
|
|
b.RunParallel(func(pb *testing.PB) {
|
|
i := 0
|
|
for pb.Next() {
|
|
switch i % 4 {
|
|
case 0:
|
|
_ = gs.GetNumberHarvests()
|
|
case 1:
|
|
_ = gs.GetCollectionSkill()
|
|
case 2:
|
|
_ = gs.IsAvailable()
|
|
case 3:
|
|
_ = gs.GetHarvestSpellType()
|
|
}
|
|
i++
|
|
}
|
|
})
|
|
})
|
|
|
|
b.Run("GroundSpawnConcurrentWrites", func(b *testing.B) {
|
|
config := GroundSpawnConfig{
|
|
GroundSpawnID: 1,
|
|
CollectionSkill: SkillGathering,
|
|
NumberHarvests: 10,
|
|
AttemptsPerHarvest: 1,
|
|
Location: SpawnLocation{
|
|
X: 100, Y: 200, Z: 300, Heading: 45, GridID: 1,
|
|
},
|
|
Name: "Concurrent Node",
|
|
Description: "Concurrent benchmark node",
|
|
}
|
|
gs := NewGroundSpawn(config)
|
|
|
|
b.ResetTimer()
|
|
b.RunParallel(func(pb *testing.PB) {
|
|
i := 0
|
|
for pb.Next() {
|
|
switch i % 3 {
|
|
case 0:
|
|
gs.SetNumberHarvests(int8(i % 10))
|
|
case 1:
|
|
gs.SetCollectionSkill(SkillMining)
|
|
case 2:
|
|
gs.SetRandomizeHeading(i%2 == 0)
|
|
}
|
|
i++
|
|
}
|
|
})
|
|
})
|
|
|
|
b.Run("ManagerConcurrentOperations", func(b *testing.B) {
|
|
manager := NewManager(nil, &mockLogger{})
|
|
|
|
// Pre-populate
|
|
for i := int32(1); i <= 10; i++ {
|
|
config := GroundSpawnConfig{
|
|
GroundSpawnID: i,
|
|
CollectionSkill: SkillGathering,
|
|
NumberHarvests: 5,
|
|
AttemptsPerHarvest: 1,
|
|
Location: SpawnLocation{
|
|
X: float32(i * 10), Y: float32(i * 20), Z: float32(i * 30),
|
|
Heading: 0, GridID: 1,
|
|
},
|
|
Name: "Manager Node",
|
|
Description: "Manager benchmark node",
|
|
}
|
|
manager.CreateGroundSpawn(config)
|
|
}
|
|
|
|
b.ResetTimer()
|
|
b.RunParallel(func(pb *testing.PB) {
|
|
i := 0
|
|
for pb.Next() {
|
|
spawnID := int32((i % 10) + 1)
|
|
switch i % 5 {
|
|
case 0:
|
|
_ = manager.GetGroundSpawn(spawnID)
|
|
case 1:
|
|
_ = manager.GetGroundSpawnsByZone(1)
|
|
case 2:
|
|
_ = manager.GetStatistics()
|
|
case 3:
|
|
_ = manager.GetActiveGroundSpawns()
|
|
case 4:
|
|
manager.ProcessRespawns()
|
|
}
|
|
i++
|
|
}
|
|
})
|
|
})
|
|
}
|
|
|
|
// Memory allocation benchmarks
|
|
func BenchmarkMemoryAllocations(b *testing.B) {
|
|
b.Run("GroundSpawnCreation", func(b *testing.B) {
|
|
config := GroundSpawnConfig{
|
|
GroundSpawnID: 1,
|
|
CollectionSkill: SkillGathering,
|
|
NumberHarvests: 5,
|
|
AttemptsPerHarvest: 1,
|
|
Location: SpawnLocation{
|
|
X: 100, Y: 200, Z: 300, Heading: 45, GridID: 1,
|
|
},
|
|
Name: "Memory Test Node",
|
|
Description: "Memory test node",
|
|
}
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for b.Loop() {
|
|
_ = NewGroundSpawn(config)
|
|
}
|
|
})
|
|
|
|
b.Run("ManagerCreation", func(b *testing.B) {
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for b.Loop() {
|
|
_ = NewManager(nil, &mockLogger{})
|
|
}
|
|
})
|
|
|
|
b.Run("GroundSpawnCopy", func(b *testing.B) {
|
|
config := GroundSpawnConfig{
|
|
GroundSpawnID: 1,
|
|
CollectionSkill: SkillGathering,
|
|
NumberHarvests: 5,
|
|
AttemptsPerHarvest: 1,
|
|
Location: SpawnLocation{
|
|
X: 100, Y: 200, Z: 300, Heading: 45, GridID: 1,
|
|
},
|
|
Name: "Copy Test Node",
|
|
Description: "Copy test node",
|
|
}
|
|
gs := NewGroundSpawn(config)
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for b.Loop() {
|
|
_ = gs.Copy()
|
|
}
|
|
})
|
|
|
|
b.Run("StatisticsGeneration", func(b *testing.B) {
|
|
manager := NewManager(nil, &mockLogger{})
|
|
|
|
// Add some data for meaningful statistics
|
|
for i := int32(1); i <= 10; i++ {
|
|
config := GroundSpawnConfig{
|
|
GroundSpawnID: i,
|
|
CollectionSkill: SkillGathering,
|
|
NumberHarvests: 5,
|
|
AttemptsPerHarvest: 1,
|
|
Location: SpawnLocation{
|
|
X: float32(i * 10), Y: float32(i * 20), Z: float32(i * 30),
|
|
Heading: 0, GridID: 1,
|
|
},
|
|
Name: "Stats Node",
|
|
Description: "Stats test node",
|
|
}
|
|
manager.CreateGroundSpawn(config)
|
|
}
|
|
|
|
// Add some harvest statistics
|
|
manager.mutex.Lock()
|
|
manager.totalHarvests = 1000
|
|
manager.successfulHarvests = 850
|
|
manager.rareItemsHarvested = 50
|
|
manager.skillUpsGenerated = 200
|
|
manager.harvestsBySkill[SkillGathering] = 600
|
|
manager.harvestsBySkill[SkillMining] = 400
|
|
manager.mutex.Unlock()
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for b.Loop() {
|
|
_ = manager.GetStatistics()
|
|
}
|
|
})
|
|
}
|
|
|
|
// Contention benchmarks
|
|
func BenchmarkContention(b *testing.B) {
|
|
b.Run("HighContentionReads", func(b *testing.B) {
|
|
config := GroundSpawnConfig{
|
|
GroundSpawnID: 1,
|
|
CollectionSkill: SkillGathering,
|
|
NumberHarvests: 10,
|
|
AttemptsPerHarvest: 1,
|
|
Location: SpawnLocation{
|
|
X: 100, Y: 200, Z: 300, Heading: 45, GridID: 1,
|
|
},
|
|
Name: "Contention Node",
|
|
Description: "Contention test node",
|
|
}
|
|
gs := NewGroundSpawn(config)
|
|
|
|
b.ResetTimer()
|
|
b.RunParallel(func(pb *testing.PB) {
|
|
for pb.Next() {
|
|
_ = gs.GetNumberHarvests()
|
|
}
|
|
})
|
|
})
|
|
|
|
b.Run("HighContentionWrites", func(b *testing.B) {
|
|
config := GroundSpawnConfig{
|
|
GroundSpawnID: 1,
|
|
CollectionSkill: SkillGathering,
|
|
NumberHarvests: 10,
|
|
AttemptsPerHarvest: 1,
|
|
Location: SpawnLocation{
|
|
X: 100, Y: 200, Z: 300, Heading: 45, GridID: 1,
|
|
},
|
|
Name: "Contention Node",
|
|
Description: "Contention test node",
|
|
}
|
|
gs := NewGroundSpawn(config)
|
|
|
|
b.ResetTimer()
|
|
b.RunParallel(func(pb *testing.PB) {
|
|
i := 0
|
|
for pb.Next() {
|
|
gs.SetNumberHarvests(int8(i % 10))
|
|
i++
|
|
}
|
|
})
|
|
})
|
|
|
|
b.Run("MixedReadWrite", func(b *testing.B) {
|
|
config := GroundSpawnConfig{
|
|
GroundSpawnID: 1,
|
|
CollectionSkill: SkillGathering,
|
|
NumberHarvests: 10,
|
|
AttemptsPerHarvest: 1,
|
|
Location: SpawnLocation{
|
|
X: 100, Y: 200, Z: 300, Heading: 45, GridID: 1,
|
|
},
|
|
Name: "Mixed Node",
|
|
Description: "Mixed operations test node",
|
|
}
|
|
gs := NewGroundSpawn(config)
|
|
|
|
b.ResetTimer()
|
|
b.RunParallel(func(pb *testing.PB) {
|
|
i := 0
|
|
for pb.Next() {
|
|
if i%10 == 0 {
|
|
// 10% writes
|
|
gs.SetNumberHarvests(int8(i % 5))
|
|
} else {
|
|
// 90% reads
|
|
_ = gs.GetNumberHarvests()
|
|
}
|
|
i++
|
|
}
|
|
})
|
|
})
|
|
|
|
b.Run("ManagerHighContention", func(b *testing.B) {
|
|
manager := NewManager(nil, &mockLogger{})
|
|
|
|
// Pre-populate
|
|
for i := int32(1); i <= 5; i++ {
|
|
config := GroundSpawnConfig{
|
|
GroundSpawnID: i,
|
|
CollectionSkill: SkillGathering,
|
|
NumberHarvests: 5,
|
|
AttemptsPerHarvest: 1,
|
|
Location: SpawnLocation{
|
|
X: float32(i * 10), Y: float32(i * 20), Z: float32(i * 30),
|
|
Heading: 0, GridID: 1,
|
|
},
|
|
Name: "Contention Node",
|
|
Description: "Manager contention test",
|
|
}
|
|
manager.CreateGroundSpawn(config)
|
|
}
|
|
|
|
b.ResetTimer()
|
|
b.RunParallel(func(pb *testing.PB) {
|
|
for pb.Next() {
|
|
_ = manager.GetGroundSpawn(1)
|
|
}
|
|
})
|
|
})
|
|
}
|
|
|
|
// Scalability benchmarks
|
|
func BenchmarkScalability(b *testing.B) {
|
|
sizes := []int{10, 100, 1000}
|
|
|
|
for _, size := range sizes {
|
|
b.Run("GroundSpawnLookup_"+string(rune(size)), func(b *testing.B) {
|
|
manager := NewManager(nil, &mockLogger{})
|
|
|
|
// Pre-populate with varying sizes
|
|
for i := int32(1); i <= int32(size); i++ {
|
|
config := GroundSpawnConfig{
|
|
GroundSpawnID: i,
|
|
CollectionSkill: SkillGathering,
|
|
NumberHarvests: 5,
|
|
AttemptsPerHarvest: 1,
|
|
Location: SpawnLocation{
|
|
X: float32(i * 10), Y: float32(i * 20), Z: float32(i * 30),
|
|
Heading: 0, GridID: 1,
|
|
},
|
|
Name: "Scale Node",
|
|
Description: "Scalability test node",
|
|
}
|
|
manager.CreateGroundSpawn(config)
|
|
}
|
|
|
|
b.ResetTimer()
|
|
for i := 0; b.Loop(); i++ {
|
|
spawnID := int32((i % size) + 1)
|
|
_ = manager.GetGroundSpawn(spawnID)
|
|
}
|
|
})
|
|
}
|
|
|
|
for _, size := range sizes {
|
|
b.Run("ZoneLookup_"+string(rune(size)), func(b *testing.B) {
|
|
manager := NewManager(nil, &mockLogger{})
|
|
|
|
// Pre-populate with varying sizes
|
|
for i := int32(1); i <= int32(size); i++ {
|
|
config := GroundSpawnConfig{
|
|
GroundSpawnID: i,
|
|
CollectionSkill: SkillGathering,
|
|
NumberHarvests: 5,
|
|
AttemptsPerHarvest: 1,
|
|
Location: SpawnLocation{
|
|
X: float32(i * 10), Y: float32(i * 20), Z: float32(i * 30),
|
|
Heading: 0, GridID: 1,
|
|
},
|
|
Name: "Zone Node",
|
|
Description: "Zone scalability test",
|
|
}
|
|
manager.CreateGroundSpawn(config)
|
|
}
|
|
|
|
b.ResetTimer()
|
|
for b.Loop() {
|
|
_ = manager.GetGroundSpawnsByZone(1)
|
|
}
|
|
})
|
|
}
|
|
}
|