package common import ( "fmt" "math/rand" "testing" ) // testItem implements Identifiable for benchmarking type testItem struct { id int32 name string value int32 flag bool } func (t *testItem) GetID() int32 { return t.id } // BenchmarkMasterListOperations benchmarks the generic MasterList func BenchmarkMasterListOperations(b *testing.B) { // Create master list with test data ml := NewMasterList[int32, *testItem]() const numItems = 10000 // Pre-populate b.StopTimer() for i := 0; i < numItems; i++ { item := &testItem{ id: int32(i + 1), name: fmt.Sprintf("Item %d", i+1), value: int32(rand.Intn(100)), flag: rand.Intn(2) == 1, } ml.Add(item) } b.StartTimer() b.Run("Get", func(b *testing.B) { b.RunParallel(func(pb *testing.PB) { for pb.Next() { id := int32(rand.Intn(numItems) + 1) _ = ml.Get(id) } }) }) b.Run("Filter_10Percent", func(b *testing.B) { for i := 0; i < b.N; i++ { _ = ml.Filter(func(item *testItem) bool { return item.value < 10 // ~10% match }) } }) b.Run("Filter_50Percent", func(b *testing.B) { for i := 0; i < b.N; i++ { _ = ml.Filter(func(item *testItem) bool { return item.value < 50 // ~50% match }) } }) b.Run("Filter_90Percent", func(b *testing.B) { for i := 0; i < b.N; i++ { _ = ml.Filter(func(item *testItem) bool { return item.value < 90 // ~90% match }) } }) b.Run("Count_10Percent", func(b *testing.B) { for i := 0; i < b.N; i++ { _ = ml.Count(func(item *testItem) bool { return item.value < 10 }) } }) b.Run("Count_50Percent", func(b *testing.B) { for i := 0; i < b.N; i++ { _ = ml.Count(func(item *testItem) bool { return item.value < 50 }) } }) b.Run("Find", func(b *testing.B) { for i := 0; i < b.N; i++ { targetValue := int32(rand.Intn(100)) _, _ = ml.Find(func(item *testItem) bool { return item.value == targetValue }) } }) b.Run("ForEach", func(b *testing.B) { for i := 0; i < b.N; i++ { ml.ForEach(func(id int32, item *testItem) { _ = item.value + 1 // Minimal work }) } }) b.Run("WithReadLock", func(b *testing.B) { for i := 0; i < b.N; i++ { ml.WithReadLock(func(items map[int32]*testItem) { count := 0 for _, item := range items { if item.value < 50 { count++ } } _ = count }) } }) b.Run("FilterWithCapacity_Accurate", func(b *testing.B) { for i := 0; i < b.N; i++ { _ = ml.FilterWithCapacity(func(item *testItem) bool { return item.value < 50 }, 5000) // Accurate estimate: 50% of 10k = 5k } }) b.Run("FilterInto_Reuse", func(b *testing.B) { var reusableSlice []*testItem for i := 0; i < b.N; i++ { reusableSlice = ml.FilterInto(func(item *testItem) bool { return item.value < 50 }, reusableSlice) } }) b.Run("CountAndFilter_Combined", func(b *testing.B) { for i := 0; i < b.N; i++ { _, _ = ml.CountAndFilter(func(item *testItem) bool { return item.value < 50 }) } }) } // BenchmarkMemoryAllocations tests allocation patterns func BenchmarkMemoryAllocations(b *testing.B) { ml := NewMasterList[int32, *testItem]() const numItems = 1000 // Pre-populate for i := 0; i < numItems; i++ { item := &testItem{ id: int32(i + 1), name: fmt.Sprintf("Item %d", i+1), value: int32(rand.Intn(100)), flag: rand.Intn(2) == 1, } ml.Add(item) } b.Run("Filter_Allocations", func(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { _ = ml.Filter(func(item *testItem) bool { return item.value < 50 }) } }) b.Run("GetAll_Allocations", func(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { _ = ml.GetAll() } }) b.Run("GetAllSlice_Allocations", func(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { _ = ml.GetAllSlice() } }) b.Run("FilterWithCapacity_Allocations", func(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { _ = ml.FilterWithCapacity(func(item *testItem) bool { return item.value < 50 }, 500) // Accurate capacity estimate } }) b.Run("FilterInto_Allocations", func(b *testing.B) { b.ReportAllocs() reusableSlice := make([]*testItem, 0, 600) // Pre-sized for i := 0; i < b.N; i++ { reusableSlice = ml.FilterInto(func(item *testItem) bool { return item.value < 50 }, reusableSlice) } }) b.Run("CountAndFilter_Allocations", func(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { _, _ = ml.CountAndFilter(func(item *testItem) bool { return item.value < 50 }) } }) }