371 lines
8.3 KiB
Go
371 lines
8.3 KiB
Go
package chat
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
|
|
"eq2emu/internal/database"
|
|
)
|
|
|
|
// Setup creates a master list with test data for benchmarking
|
|
func benchmarkSetup() *MasterList {
|
|
db, _ := database.NewSQLite("file::memory:?mode=memory&cache=shared")
|
|
|
|
masterList := NewMasterList()
|
|
|
|
// Add world channels
|
|
worldChannels := []string{
|
|
"Auction", "Trade", "General", "OOC", "LFG", "Crafting",
|
|
"Roleplay", "Newbie", "Antonica", "Commonlands",
|
|
"Freeport", "Qeynos", "Kelethin", "Neriak",
|
|
}
|
|
|
|
for i, name := range worldChannels {
|
|
ch := NewWithData(int32(i+1), name, ChannelTypeWorld, db)
|
|
if i%3 == 0 {
|
|
ch.SetLevelRestriction(10) // Some have level restrictions
|
|
}
|
|
if i%4 == 0 {
|
|
ch.SetRacesAllowed(1 << 1) // Some have race restrictions
|
|
}
|
|
masterList.AddChannel(ch)
|
|
|
|
// Add some members to channels
|
|
if i%2 == 0 {
|
|
ch.JoinChannel(int32(1000 + i))
|
|
}
|
|
if i%3 == 0 {
|
|
ch.JoinChannel(int32(2000 + i))
|
|
}
|
|
}
|
|
|
|
// Add custom channels
|
|
for i := 0; i < 50; i++ {
|
|
ch := NewWithData(int32(100+i), fmt.Sprintf("CustomChannel%d", i), ChannelTypeCustom, db)
|
|
if i%5 == 0 {
|
|
ch.SetLevelRestriction(20)
|
|
}
|
|
masterList.AddChannel(ch)
|
|
|
|
// Add members to some custom channels
|
|
if i%4 == 0 {
|
|
ch.JoinChannel(int32(3000 + i))
|
|
}
|
|
}
|
|
|
|
return masterList
|
|
}
|
|
|
|
func BenchmarkMasterList_AddChannel(b *testing.B) {
|
|
db, _ := database.NewSQLite("file::memory:?mode=memory&cache=shared")
|
|
defer db.Close()
|
|
|
|
masterList := NewMasterList()
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
ch := NewWithData(int32(i+10000), fmt.Sprintf("Channel%d", i), ChannelTypeWorld, db)
|
|
masterList.AddChannel(ch)
|
|
}
|
|
}
|
|
|
|
func BenchmarkMasterList_GetChannel(b *testing.B) {
|
|
masterList := benchmarkSetup()
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
masterList.GetChannel(int32(i%64 + 1))
|
|
}
|
|
}
|
|
|
|
func BenchmarkMasterList_GetChannelSafe(b *testing.B) {
|
|
masterList := benchmarkSetup()
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
masterList.GetChannelSafe(int32(i%64 + 1))
|
|
}
|
|
}
|
|
|
|
func BenchmarkMasterList_HasChannel(b *testing.B) {
|
|
masterList := benchmarkSetup()
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
masterList.HasChannel(int32(i%64 + 1))
|
|
}
|
|
}
|
|
|
|
func BenchmarkMasterList_FindChannelsByType(b *testing.B) {
|
|
masterList := benchmarkSetup()
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
if i%2 == 0 {
|
|
masterList.FindChannelsByType(ChannelTypeWorld)
|
|
} else {
|
|
masterList.FindChannelsByType(ChannelTypeCustom)
|
|
}
|
|
}
|
|
}
|
|
|
|
func BenchmarkMasterList_GetWorldChannels(b *testing.B) {
|
|
masterList := benchmarkSetup()
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
masterList.GetWorldChannels()
|
|
}
|
|
}
|
|
|
|
func BenchmarkMasterList_GetCustomChannels(b *testing.B) {
|
|
masterList := benchmarkSetup()
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
masterList.GetCustomChannels()
|
|
}
|
|
}
|
|
|
|
func BenchmarkMasterList_GetChannelByName(b *testing.B) {
|
|
masterList := benchmarkSetup()
|
|
names := []string{"auction", "trade", "general", "ooc", "customchannel5", "customchannel15"}
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
masterList.GetChannelByName(names[i%len(names)])
|
|
}
|
|
}
|
|
|
|
func BenchmarkMasterList_FindChannelsByName(b *testing.B) {
|
|
masterList := benchmarkSetup()
|
|
searchTerms := []string{"Auction", "Custom", "Channel", "Trade", "General"}
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
masterList.FindChannelsByName(searchTerms[i%len(searchTerms)])
|
|
}
|
|
}
|
|
|
|
func BenchmarkMasterList_GetActiveChannels(b *testing.B) {
|
|
masterList := benchmarkSetup()
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
masterList.GetActiveChannels()
|
|
}
|
|
}
|
|
|
|
func BenchmarkMasterList_GetEmptyChannels(b *testing.B) {
|
|
masterList := benchmarkSetup()
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
masterList.GetEmptyChannels()
|
|
}
|
|
}
|
|
|
|
func BenchmarkMasterList_GetCompatibleChannels(b *testing.B) {
|
|
masterList := benchmarkSetup()
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
level := int32(i%50 + 1)
|
|
race := int32(i%10 + 1)
|
|
class := int32(i%20 + 1)
|
|
masterList.GetCompatibleChannels(level, race, class)
|
|
}
|
|
}
|
|
|
|
func BenchmarkMasterList_GetChannelsByMemberCount(b *testing.B) {
|
|
masterList := benchmarkSetup()
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
memberCount := i % 5 // 0-4 members
|
|
masterList.GetChannelsByMemberCount(memberCount)
|
|
}
|
|
}
|
|
|
|
func BenchmarkMasterList_GetChannelsByLevelRestriction(b *testing.B) {
|
|
masterList := benchmarkSetup()
|
|
levels := []int32{0, 10, 20, 30, 50}
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
masterList.GetChannelsByLevelRestriction(levels[i%len(levels)])
|
|
}
|
|
}
|
|
|
|
func BenchmarkMasterList_GetAllChannels(b *testing.B) {
|
|
masterList := benchmarkSetup()
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
masterList.GetAllChannels()
|
|
}
|
|
}
|
|
|
|
func BenchmarkMasterList_GetAllChannelsList(b *testing.B) {
|
|
masterList := benchmarkSetup()
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
masterList.GetAllChannelsList()
|
|
}
|
|
}
|
|
|
|
func BenchmarkMasterList_GetStatistics(b *testing.B) {
|
|
masterList := benchmarkSetup()
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
masterList.GetStatistics()
|
|
}
|
|
}
|
|
|
|
func BenchmarkMasterList_ValidateChannels(b *testing.B) {
|
|
masterList := benchmarkSetup()
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
masterList.ValidateChannels()
|
|
}
|
|
}
|
|
|
|
func BenchmarkMasterList_RemoveChannel(b *testing.B) {
|
|
b.StopTimer()
|
|
masterList := benchmarkSetup()
|
|
initialCount := masterList.GetChannelCount()
|
|
|
|
// Pre-populate with channels we'll remove
|
|
db, _ := database.NewSQLite("file::memory:?mode=memory&cache=shared")
|
|
for i := 0; i < b.N; i++ {
|
|
ch := NewWithData(int32(20000+i), fmt.Sprintf("ToRemove%d", i), ChannelTypeCustom, db)
|
|
masterList.AddChannel(ch)
|
|
}
|
|
|
|
b.StartTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
masterList.RemoveChannel(int32(20000 + i))
|
|
}
|
|
|
|
b.StopTimer()
|
|
if masterList.GetChannelCount() != initialCount {
|
|
b.Errorf("Expected %d channels after removal, got %d", initialCount, masterList.GetChannelCount())
|
|
}
|
|
}
|
|
|
|
func BenchmarkMasterList_ForEach(b *testing.B) {
|
|
masterList := benchmarkSetup()
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
count := 0
|
|
masterList.ForEach(func(id int32, channel *Channel) {
|
|
count++
|
|
})
|
|
}
|
|
}
|
|
|
|
func BenchmarkMasterList_UpdateChannel(b *testing.B) {
|
|
masterList := benchmarkSetup()
|
|
db, _ := database.NewSQLite("file::memory:?mode=memory&cache=shared")
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
channelID := int32(i%64 + 1)
|
|
updatedChannel := &Channel{
|
|
ID: channelID,
|
|
Name: fmt.Sprintf("Updated%d", i),
|
|
ChannelType: ChannelTypeCustom,
|
|
db: db,
|
|
isNew: false,
|
|
members: make([]int32, 0),
|
|
}
|
|
masterList.UpdateChannel(updatedChannel)
|
|
}
|
|
}
|
|
|
|
// Memory allocation benchmarks
|
|
func BenchmarkMasterList_GetChannel_Allocs(b *testing.B) {
|
|
masterList := benchmarkSetup()
|
|
|
|
b.ResetTimer()
|
|
b.ReportAllocs()
|
|
for i := 0; i < b.N; i++ {
|
|
masterList.GetChannel(int32(i%64 + 1))
|
|
}
|
|
}
|
|
|
|
func BenchmarkMasterList_FindChannelsByType_Allocs(b *testing.B) {
|
|
masterList := benchmarkSetup()
|
|
|
|
b.ResetTimer()
|
|
b.ReportAllocs()
|
|
for i := 0; i < b.N; i++ {
|
|
masterList.FindChannelsByType(ChannelTypeWorld)
|
|
}
|
|
}
|
|
|
|
func BenchmarkMasterList_GetChannelByName_Allocs(b *testing.B) {
|
|
masterList := benchmarkSetup()
|
|
|
|
b.ResetTimer()
|
|
b.ReportAllocs()
|
|
for i := 0; i < b.N; i++ {
|
|
masterList.GetChannelByName("auction")
|
|
}
|
|
}
|
|
|
|
// Concurrent benchmark
|
|
func BenchmarkMasterList_ConcurrentReads(b *testing.B) {
|
|
masterList := benchmarkSetup()
|
|
|
|
b.ResetTimer()
|
|
b.RunParallel(func(pb *testing.PB) {
|
|
for pb.Next() {
|
|
// Mix of read operations
|
|
switch b.N % 5 {
|
|
case 0:
|
|
masterList.GetChannel(int32(b.N%64 + 1))
|
|
case 1:
|
|
masterList.FindChannelsByType(ChannelTypeWorld)
|
|
case 2:
|
|
masterList.GetChannelByName("auction")
|
|
case 3:
|
|
masterList.GetActiveChannels()
|
|
case 4:
|
|
masterList.GetCompatibleChannels(25, 1, 1)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
func BenchmarkMasterList_ConcurrentMixed(b *testing.B) {
|
|
masterList := benchmarkSetup()
|
|
db, _ := database.NewSQLite("file::memory:?mode=memory&cache=shared")
|
|
|
|
b.ResetTimer()
|
|
b.RunParallel(func(pb *testing.PB) {
|
|
for pb.Next() {
|
|
// Mix of read and write operations (mostly reads)
|
|
switch b.N % 10 {
|
|
case 0: // 10% writes
|
|
ch := NewWithData(int32(b.N+50000), fmt.Sprintf("Concurrent%d", b.N), ChannelTypeCustom, db)
|
|
masterList.AddChannel(ch)
|
|
default: // 90% reads
|
|
switch b.N % 4 {
|
|
case 0:
|
|
masterList.GetChannel(int32(b.N%64 + 1))
|
|
case 1:
|
|
masterList.FindChannelsByType(ChannelTypeWorld)
|
|
case 2:
|
|
masterList.GetChannelByName("auction")
|
|
case 3:
|
|
masterList.GetActiveChannels()
|
|
}
|
|
}
|
|
}
|
|
})
|
|
} |