1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package atomic
22
23 import (
24 "errors"
25 "math"
26 "runtime"
27 "sync"
28 "sync/atomic"
29 "testing"
30 "time"
31 )
32
33 const (
34 _parallelism = 4
35 _iterations = 1000
36 )
37
38 var _stressTests = map[string]func() func(){
39 "i32/std": stressStdInt32,
40 "i32": stressInt32,
41 "i64/std": stressStdInt64,
42 "i64": stressInt64,
43 "u32/std": stressStdUint32,
44 "u32": stressUint32,
45 "u64/std": stressStdUint64,
46 "u64": stressUint64,
47 "f64": stressFloat64,
48 "bool": stressBool,
49 "string": stressString,
50 "duration": stressDuration,
51 "error": stressError,
52 "time": stressTime,
53 }
54
55 func TestStress(t *testing.T) {
56 for name, ff := range _stressTests {
57 t.Run(name, func(t *testing.T) {
58 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(_parallelism))
59
60 start := make(chan struct{})
61 var wg sync.WaitGroup
62 wg.Add(_parallelism)
63 f := ff()
64 for i := 0; i < _parallelism; i++ {
65 go func() {
66 defer wg.Done()
67 <-start
68 for j := 0; j < _iterations; j++ {
69 f()
70 }
71 }()
72 }
73 close(start)
74 wg.Wait()
75 })
76 }
77 }
78
79 func BenchmarkStress(b *testing.B) {
80 for name, ff := range _stressTests {
81 b.Run(name, func(b *testing.B) {
82 f := ff()
83
84 b.Run("serial", func(b *testing.B) {
85 for i := 0; i < b.N; i++ {
86 f()
87 }
88 })
89
90 b.Run("parallel", func(b *testing.B) {
91 b.RunParallel(func(pb *testing.PB) {
92 for pb.Next() {
93 f()
94 }
95 })
96 })
97 })
98 }
99 }
100
101 func stressStdInt32() func() {
102 var atom int32
103 return func() {
104 atomic.LoadInt32(&atom)
105 atomic.AddInt32(&atom, 1)
106 atomic.AddInt32(&atom, -2)
107 atomic.AddInt32(&atom, 1)
108 atomic.AddInt32(&atom, -1)
109 atomic.CompareAndSwapInt32(&atom, 1, 0)
110 atomic.SwapInt32(&atom, 5)
111 atomic.StoreInt32(&atom, 1)
112 }
113 }
114
115 func stressInt32() func() {
116 var atom Int32
117 return func() {
118 atom.Load()
119 atom.Add(1)
120 atom.Sub(2)
121 atom.Inc()
122 atom.Dec()
123 atom.CAS(1, 0)
124 atom.Swap(5)
125 atom.Store(1)
126 }
127 }
128
129 func stressStdInt64() func() {
130 var atom int64
131 return func() {
132 atomic.LoadInt64(&atom)
133 atomic.AddInt64(&atom, 1)
134 atomic.AddInt64(&atom, -2)
135 atomic.AddInt64(&atom, 1)
136 atomic.AddInt64(&atom, -1)
137 atomic.CompareAndSwapInt64(&atom, 1, 0)
138 atomic.SwapInt64(&atom, 5)
139 atomic.StoreInt64(&atom, 1)
140 }
141 }
142
143 func stressInt64() func() {
144 var atom Int64
145 return func() {
146 atom.Load()
147 atom.Add(1)
148 atom.Sub(2)
149 atom.Inc()
150 atom.Dec()
151 atom.CAS(1, 0)
152 atom.Swap(5)
153 atom.Store(1)
154 }
155 }
156
157 func stressStdUint32() func() {
158 var atom uint32
159 return func() {
160 atomic.LoadUint32(&atom)
161 atomic.AddUint32(&atom, 1)
162
163 atomic.AddUint32(&atom, math.MaxUint32-1)
164 atomic.AddUint32(&atom, 1)
165 atomic.AddUint32(&atom, math.MaxUint32)
166 atomic.CompareAndSwapUint32(&atom, 1, 0)
167 atomic.SwapUint32(&atom, 5)
168 atomic.StoreUint32(&atom, 1)
169 }
170 }
171
172 func stressUint32() func() {
173 var atom Uint32
174 return func() {
175 atom.Load()
176 atom.Add(1)
177 atom.Sub(2)
178 atom.Inc()
179 atom.Dec()
180 atom.CAS(1, 0)
181 atom.Swap(5)
182 atom.Store(1)
183 }
184 }
185
186 func stressStdUint64() func() {
187 var atom uint64
188 return func() {
189 atomic.LoadUint64(&atom)
190 atomic.AddUint64(&atom, 1)
191
192 atomic.AddUint64(&atom, math.MaxUint64-1)
193 atomic.AddUint64(&atom, 1)
194 atomic.AddUint64(&atom, math.MaxUint64)
195 atomic.CompareAndSwapUint64(&atom, 1, 0)
196 atomic.SwapUint64(&atom, 5)
197 atomic.StoreUint64(&atom, 1)
198 }
199 }
200
201 func stressUint64() func() {
202 var atom Uint64
203 return func() {
204 atom.Load()
205 atom.Add(1)
206 atom.Sub(2)
207 atom.Inc()
208 atom.Dec()
209 atom.CAS(1, 0)
210 atom.Swap(5)
211 atom.Store(1)
212 }
213 }
214
215 func stressFloat64() func() {
216 var atom Float64
217 return func() {
218 atom.Load()
219 atom.CAS(1.0, 0.1)
220 atom.Add(1.1)
221 atom.Sub(0.2)
222 atom.Store(1.0)
223 }
224 }
225
226 func stressBool() func() {
227 var atom Bool
228 return func() {
229 atom.Load()
230 atom.Store(false)
231 atom.Swap(true)
232 atom.CAS(true, false)
233 atom.CAS(true, false)
234 atom.Load()
235 atom.Toggle()
236 atom.Toggle()
237 }
238 }
239
240 func stressString() func() {
241 var atom String
242 return func() {
243 atom.Load()
244 atom.Store("abc")
245 atom.Load()
246 atom.Store("def")
247 atom.Load()
248 atom.Store("")
249 }
250 }
251
252 func stressDuration() func() {
253 var atom = NewDuration(0)
254 return func() {
255 atom.Load()
256 atom.Add(1)
257 atom.Sub(2)
258 atom.CAS(1, 0)
259 atom.Swap(5)
260 atom.Store(1)
261 }
262 }
263
264 func stressError() func() {
265 var atom = NewError(nil)
266 var err1 = errors.New("err1")
267 var err2 = errors.New("err2")
268 return func() {
269 atom.Load()
270 atom.Store(err1)
271 atom.Load()
272 atom.Store(err2)
273 atom.Load()
274 atom.Store(nil)
275 }
276 }
277
278 func stressTime() func() {
279 var atom = NewTime(time.Date(2021, 6, 17, 9, 0, 0, 0, time.UTC))
280 var dayAgo = time.Date(2021, 6, 16, 9, 0, 0, 0, time.UTC)
281 var weekAgo = time.Date(2021, 6, 10, 9, 0, 0, 0, time.UTC)
282 return func() {
283 atom.Load()
284 atom.Store(dayAgo)
285 atom.Load()
286 atom.Store(weekAgo)
287 atom.Store(time.Time{})
288 }
289 }
290
View as plain text