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  }