|
4 | 4 | "fmt"
|
5 | 5 | "math/rand"
|
6 | 6 | "strconv"
|
| 7 | + "sync" |
7 | 8 | "testing"
|
8 | 9 | "time"
|
9 | 10 | )
|
@@ -60,6 +61,35 @@ func TestChooser_Pick(t *testing.T) {
|
60 | 61 | verifyFrequencyCounts(t, counts, choices)
|
61 | 62 | }
|
62 | 63 |
|
| 64 | +// TestChooser_PickSource is the same test methodology as TestChooser_Pick, but |
| 65 | +// here we use the PickSource method and access the same chooser concurrently |
| 66 | +// from multiple different goroutines, each providing its own source of |
| 67 | +// randomness. |
| 68 | +func TestChooser_PickSource(t *testing.T) { |
| 69 | + choices := mockFrequencyChoices(t, testChoices) |
| 70 | + chooser := NewChooser(choices...) |
| 71 | + t.Log("totals in chooser", chooser.totals) |
| 72 | + |
| 73 | + counts1 := make(map[int]int) |
| 74 | + counts2 := make(map[int]int) |
| 75 | + var wg sync.WaitGroup |
| 76 | + wg.Add(2) |
| 77 | + checker := func(counts map[int]int) { |
| 78 | + defer wg.Done() |
| 79 | + rs := rand.New(rand.NewSource(time.Now().UTC().UnixNano())) |
| 80 | + for i := 0; i < testIterations/2; i++ { |
| 81 | + c := chooser.PickSource(rs) |
| 82 | + counts[c.(int)]++ |
| 83 | + } |
| 84 | + } |
| 85 | + go checker(counts1) |
| 86 | + go checker(counts2) |
| 87 | + wg.Wait() |
| 88 | + |
| 89 | + verifyFrequencyCounts(t, counts1, choices) |
| 90 | + verifyFrequencyCounts(t, counts2, choices) |
| 91 | +} |
| 92 | + |
63 | 93 | // Similar to what is used in randutil test, but in randomized order to avoid
|
64 | 94 | // any issues with algorithms that are accidentally dependant on presorted data.
|
65 | 95 | func mockFrequencyChoices(t *testing.T, n int) []Choice {
|
@@ -127,6 +157,22 @@ func BenchmarkPick(b *testing.B) {
|
127 | 157 | }
|
128 | 158 | }
|
129 | 159 |
|
| 160 | +func BenchmarkPickParallel(b *testing.B) { |
| 161 | + for n := BMminChoices; n <= BMmaxChoices; n *= 10 { |
| 162 | + b.Run(strconv.Itoa(n), func(b *testing.B) { |
| 163 | + choices := mockChoices(n) |
| 164 | + chooser := NewChooser(choices...) |
| 165 | + b.ResetTimer() |
| 166 | + b.RunParallel(func(pb *testing.PB) { |
| 167 | + rs := rand.New(rand.NewSource(time.Now().UTC().UnixNano())) |
| 168 | + for pb.Next() { |
| 169 | + chooser.PickSource(rs) |
| 170 | + } |
| 171 | + }) |
| 172 | + }) |
| 173 | + } |
| 174 | +} |
| 175 | + |
130 | 176 | func mockChoices(n int) []Choice {
|
131 | 177 | choices := make([]Choice, 0, n)
|
132 | 178 | for i := 0; i < n; i++ {
|
|
0 commit comments