github.com/bruceshao/lockfree@v1.1.3-0.20230816090528-e89824c0a6e9/padding_test.go (about) 1 package lockfree 2 3 import ( 4 "runtime" 5 "sync" 6 "testing" 7 ) 8 9 type foo struct { 10 x, y, z int64 11 } 12 type foo64Start struct { 13 _ [64]byte 14 x, y, z int64 15 } 16 type foo64StartEnd struct { 17 _ [64]byte 18 x, y, z int64 19 _ [64]byte 20 } 21 type foo128Start struct { 22 _ [128]byte 23 x, y, z int64 24 } 25 type foo128StartEnd struct { 26 _ [128]byte 27 x, y, z int64 28 _ [128]byte 29 } 30 type foo64StartEndAligned struct { 31 _ [64]byte 32 x, y, z int64 33 _ [64 - 24]byte 34 } 35 type foo128StartEndAligned struct { 36 _ [128]byte 37 x, y, z int64 38 _ [128 - 24]byte 39 } 40 41 const iter = (1 << 16) 42 43 func BenchmarkFalseSharing(b *testing.B) { 44 var wg sync.WaitGroup 45 b.Run("NoPad", func(b *testing.B) { 46 arr := make([]foo, runtime.GOMAXPROCS(0)) 47 arrChan := make([]chan struct{}, runtime.GOMAXPROCS(0)) 48 for i := range arrChan { 49 arrChan[i] = make(chan struct{}) 50 } 51 for i := range arr { 52 go func(i int) { 53 for range arrChan[i] { 54 for j := 0; j < iter; j++ { 55 arr[i].x++ 56 } 57 wg.Done() 58 } 59 }(i) 60 } 61 b.ResetTimer() 62 for i := 0; i < b.N; i++ { 63 wg.Add(runtime.GOMAXPROCS(0)) 64 for j := range arrChan { 65 arrChan[j] <- struct{}{} 66 } 67 wg.Wait() 68 } 69 b.StopTimer() 70 for i := range arrChan { 71 close(arrChan[i]) 72 } 73 }) 74 b.Run("Pad64Start", func(b *testing.B) { 75 arr := make([]foo64Start, runtime.GOMAXPROCS(0)) 76 arrChan := make([]chan struct{}, runtime.GOMAXPROCS(0)) 77 for i := range arrChan { 78 arrChan[i] = make(chan struct{}) 79 } 80 for i := range arr { 81 go func(i int) { 82 for range arrChan[i] { 83 for j := 0; j < iter; j++ { 84 arr[i].x++ 85 } 86 wg.Done() 87 } 88 }(i) 89 } 90 b.ResetTimer() 91 for i := 0; i < b.N; i++ { 92 wg.Add(runtime.GOMAXPROCS(0)) 93 for j := range arrChan { 94 arrChan[j] <- struct{}{} 95 } 96 wg.Wait() 97 } 98 b.StopTimer() 99 for i := range arrChan { 100 close(arrChan[i]) 101 } 102 }) 103 b.Run("Pad64StartEnd", func(b *testing.B) { 104 arr := make([]foo64StartEnd, runtime.GOMAXPROCS(0)) 105 arrChan := make([]chan struct{}, runtime.GOMAXPROCS(0)) 106 for i := range arrChan { 107 arrChan[i] = make(chan struct{}) 108 } 109 for i := range arr { 110 go func(i int) { 111 for range arrChan[i] { 112 for j := 0; j < iter; j++ { 113 arr[i].x++ 114 } 115 wg.Done() 116 } 117 }(i) 118 } 119 b.ResetTimer() 120 for i := 0; i < b.N; i++ { 121 wg.Add(runtime.GOMAXPROCS(0)) 122 for j := range arrChan { 123 arrChan[j] <- struct{}{} 124 } 125 wg.Wait() 126 } 127 b.StopTimer() 128 for i := range arrChan { 129 close(arrChan[i]) 130 } 131 }) 132 b.Run("Pad128Start", func(b *testing.B) { 133 arr := make([]foo128Start, runtime.GOMAXPROCS(0)) 134 arrChan := make([]chan struct{}, runtime.GOMAXPROCS(0)) 135 for i := range arrChan { 136 arrChan[i] = make(chan struct{}) 137 } 138 for i := range arr { 139 go func(i int) { 140 for range arrChan[i] { 141 for j := 0; j < iter; j++ { 142 arr[i].x++ 143 } 144 wg.Done() 145 } 146 }(i) 147 } 148 b.ResetTimer() 149 for i := 0; i < b.N; i++ { 150 wg.Add(runtime.GOMAXPROCS(0)) 151 for j := range arrChan { 152 arrChan[j] <- struct{}{} 153 } 154 wg.Wait() 155 } 156 b.StopTimer() 157 for i := range arrChan { 158 close(arrChan[i]) 159 } 160 }) 161 b.Run("Pad128StartEnd", func(b *testing.B) { 162 arr := make([]foo128StartEnd, runtime.GOMAXPROCS(0)) 163 arrChan := make([]chan struct{}, runtime.GOMAXPROCS(0)) 164 for i := range arrChan { 165 arrChan[i] = make(chan struct{}) 166 } 167 for i := range arr { 168 go func(i int) { 169 for range arrChan[i] { 170 for j := 0; j < iter; j++ { 171 arr[i].x++ 172 } 173 wg.Done() 174 } 175 }(i) 176 } 177 b.ResetTimer() 178 for i := 0; i < b.N; i++ { 179 wg.Add(runtime.GOMAXPROCS(0)) 180 for j := range arrChan { 181 arrChan[j] <- struct{}{} 182 } 183 wg.Wait() 184 } 185 b.StopTimer() 186 for i := range arrChan { 187 close(arrChan[i]) 188 } 189 }) 190 b.Run("Pad64StartEndAligned", func(b *testing.B) { 191 arr := make([]foo64StartEndAligned, runtime.GOMAXPROCS(0)) 192 arrChan := make([]chan struct{}, runtime.GOMAXPROCS(0)) 193 for i := range arrChan { 194 arrChan[i] = make(chan struct{}) 195 } 196 for i := range arr { 197 go func(i int) { 198 for range arrChan[i] { 199 for j := 0; j < iter; j++ { 200 arr[i].x++ 201 } 202 wg.Done() 203 } 204 }(i) 205 } 206 b.ResetTimer() 207 for i := 0; i < b.N; i++ { 208 wg.Add(runtime.GOMAXPROCS(0)) 209 for j := range arrChan { 210 arrChan[j] <- struct{}{} 211 } 212 wg.Wait() 213 } 214 b.StopTimer() 215 for i := range arrChan { 216 close(arrChan[i]) 217 } 218 }) 219 b.Run("Pad128StartEndAligned", func(b *testing.B) { 220 arr := make([]foo128StartEndAligned, runtime.GOMAXPROCS(0)) 221 arrChan := make([]chan struct{}, runtime.GOMAXPROCS(0)) 222 for i := range arrChan { 223 arrChan[i] = make(chan struct{}) 224 } 225 for i := range arr { 226 go func(i int) { 227 for range arrChan[i] { 228 for j := 0; j < iter; j++ { 229 arr[i].x++ 230 } 231 wg.Done() 232 } 233 }(i) 234 } 235 b.ResetTimer() 236 for i := 0; i < b.N; i++ { 237 wg.Add(runtime.GOMAXPROCS(0)) 238 for j := range arrChan { 239 arrChan[j] <- struct{}{} 240 } 241 wg.Wait() 242 } 243 b.StopTimer() 244 for i := range arrChan { 245 close(arrChan[i]) 246 } 247 }) 248 } 249 func BenchmarkTrueSharing(b *testing.B) { 250 var wg sync.WaitGroup 251 b.Run("<64", func(b *testing.B) { 252 arr := make([]foo, runtime.GOMAXPROCS(0)*iter) 253 arrChan := make([]chan struct{}, runtime.GOMAXPROCS(0)) 254 for i := range arrChan { 255 arrChan[i] = make(chan struct{}) 256 } 257 for i := range arrChan { 258 go func(i int) { 259 for range arrChan[i] { 260 for j := 0; j < iter; j++ { 261 arr[(i*iter)+j].x++ 262 } 263 wg.Done() 264 } 265 }(i) 266 } 267 b.ResetTimer() 268 for i := 0; i < b.N; i++ { 269 wg.Add(runtime.GOMAXPROCS(0)) 270 for j := range arrChan { 271 arrChan[j] <- struct{}{} 272 } 273 wg.Wait() 274 } 275 b.StopTimer() 276 for i := range arrChan { 277 close(arrChan[i]) 278 } 279 }) 280 b.Run(">64", func(b *testing.B) { 281 arr := make([]foo64Start, runtime.GOMAXPROCS(0)*iter) 282 arrChan := make([]chan struct{}, runtime.GOMAXPROCS(0)) 283 for i := range arrChan { 284 arrChan[i] = make(chan struct{}) 285 } 286 for i := range arrChan { 287 go func(i int) { 288 for range arrChan[i] { 289 for j := 0; j < iter; j++ { 290 arr[(i*iter)+j].x++ 291 } 292 wg.Done() 293 } 294 }(i) 295 } 296 b.ResetTimer() 297 for i := 0; i < b.N; i++ { 298 wg.Add(runtime.GOMAXPROCS(0)) 299 for j := range arrChan { 300 arrChan[j] <- struct{}{} 301 } 302 wg.Wait() 303 } 304 b.StopTimer() 305 for i := range arrChan { 306 close(arrChan[i]) 307 } 308 }) 309 b.Run(">128", func(b *testing.B) { 310 arr := make([]foo128Start, runtime.GOMAXPROCS(0)*iter) 311 arrChan := make([]chan struct{}, runtime.GOMAXPROCS(0)) 312 for i := range arrChan { 313 arrChan[i] = make(chan struct{}) 314 } 315 for i := range arrChan { 316 go func(i int) { 317 for range arrChan[i] { 318 for j := 0; j < iter; j++ { 319 arr[(i*iter)+j].x++ 320 } 321 wg.Done() 322 } 323 }(i) 324 } 325 b.ResetTimer() 326 for i := 0; i < b.N; i++ { 327 wg.Add(runtime.GOMAXPROCS(0)) 328 for j := range arrChan { 329 arrChan[j] <- struct{}{} 330 } 331 wg.Wait() 332 } 333 b.StopTimer() 334 for i := range arrChan { 335 close(arrChan[i]) 336 } 337 }) 338 }