github.com/bepass-org/wireguard-go@v1.0.4-rc2.0.20240304192354-ebce6572bc24/device/pools_test.go (about) 1 /* SPDX-License-Identifier: MIT 2 * 3 * Copyright (C) 2017-2023 WireGuard LLC. All Rights Reserved. 4 */ 5 6 package device 7 8 import ( 9 "math/rand" 10 "runtime" 11 "sync" 12 "sync/atomic" 13 "testing" 14 "time" 15 ) 16 17 func TestWaitPool(t *testing.T) { 18 t.Skip("Currently disabled") 19 var wg sync.WaitGroup 20 var trials atomic.Int32 21 startTrials := int32(100000) 22 if raceEnabled { 23 // This test can be very slow with -race. 24 startTrials /= 10 25 } 26 trials.Store(startTrials) 27 workers := runtime.NumCPU() + 2 28 if workers-4 <= 0 { 29 t.Skip("Not enough cores") 30 } 31 p := NewWaitPool(uint32(workers-4), func() any { return make([]byte, 16) }) 32 wg.Add(workers) 33 var max atomic.Uint32 34 updateMax := func() { 35 count := p.count.Load() 36 if count > p.max { 37 t.Errorf("count (%d) > max (%d)", count, p.max) 38 } 39 for { 40 old := max.Load() 41 if count <= old { 42 break 43 } 44 if max.CompareAndSwap(old, count) { 45 break 46 } 47 } 48 } 49 for i := 0; i < workers; i++ { 50 go func() { 51 defer wg.Done() 52 for trials.Add(-1) > 0 { 53 updateMax() 54 x := p.Get() 55 updateMax() 56 time.Sleep(time.Duration(rand.Intn(100)) * time.Microsecond) 57 updateMax() 58 p.Put(x) 59 updateMax() 60 } 61 }() 62 } 63 wg.Wait() 64 if max.Load() != p.max { 65 t.Errorf("Actual maximum count (%d) != ideal maximum count (%d)", max, p.max) 66 } 67 } 68 69 func BenchmarkWaitPool(b *testing.B) { 70 var wg sync.WaitGroup 71 var trials atomic.Int32 72 trials.Store(int32(b.N)) 73 workers := runtime.NumCPU() + 2 74 if workers-4 <= 0 { 75 b.Skip("Not enough cores") 76 } 77 p := NewWaitPool(uint32(workers-4), func() any { return make([]byte, 16) }) 78 wg.Add(workers) 79 b.ResetTimer() 80 for i := 0; i < workers; i++ { 81 go func() { 82 defer wg.Done() 83 for trials.Add(-1) > 0 { 84 x := p.Get() 85 time.Sleep(time.Duration(rand.Intn(100)) * time.Microsecond) 86 p.Put(x) 87 } 88 }() 89 } 90 wg.Wait() 91 } 92 93 func BenchmarkWaitPoolEmpty(b *testing.B) { 94 var wg sync.WaitGroup 95 var trials atomic.Int32 96 trials.Store(int32(b.N)) 97 workers := runtime.NumCPU() + 2 98 if workers-4 <= 0 { 99 b.Skip("Not enough cores") 100 } 101 p := NewWaitPool(0, func() any { return make([]byte, 16) }) 102 wg.Add(workers) 103 b.ResetTimer() 104 for i := 0; i < workers; i++ { 105 go func() { 106 defer wg.Done() 107 for trials.Add(-1) > 0 { 108 x := p.Get() 109 time.Sleep(time.Duration(rand.Intn(100)) * time.Microsecond) 110 p.Put(x) 111 } 112 }() 113 } 114 wg.Wait() 115 } 116 117 func BenchmarkSyncPool(b *testing.B) { 118 var wg sync.WaitGroup 119 var trials atomic.Int32 120 trials.Store(int32(b.N)) 121 workers := runtime.NumCPU() + 2 122 if workers-4 <= 0 { 123 b.Skip("Not enough cores") 124 } 125 p := sync.Pool{New: func() any { return make([]byte, 16) }} 126 wg.Add(workers) 127 b.ResetTimer() 128 for i := 0; i < workers; i++ { 129 go func() { 130 defer wg.Done() 131 for trials.Add(-1) > 0 { 132 x := p.Get() 133 time.Sleep(time.Duration(rand.Intn(100)) * time.Microsecond) 134 p.Put(x) 135 } 136 }() 137 } 138 wg.Wait() 139 }