Source file src/runtime/memmove_test.go

     1  // Copyright 2013 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package runtime_test
     6  
     7  import (
     8  	"crypto/rand"
     9  	"encoding/binary"
    10  	"fmt"
    11  	"internal/race"
    12  	"internal/testenv"
    13  	. "runtime"
    14  	"sync/atomic"
    15  	"testing"
    16  	"unsafe"
    17  )
    18  
    19  func TestMemmove(t *testing.T) {
    20  	if *flagQuick {
    21  		t.Skip("-quick")
    22  	}
    23  	t.Parallel()
    24  	size := 256
    25  	if testing.Short() {
    26  		size = 128 + 16
    27  	}
    28  	src := make([]byte, size)
    29  	dst := make([]byte, size)
    30  	for i := 0; i < size; i++ {
    31  		src[i] = byte(128 + (i & 127))
    32  	}
    33  	for i := 0; i < size; i++ {
    34  		dst[i] = byte(i & 127)
    35  	}
    36  	for n := 0; n <= size; n++ {
    37  		for x := 0; x <= size-n; x++ { // offset in src
    38  			for y := 0; y <= size-n; y++ { // offset in dst
    39  				copy(dst[y:y+n], src[x:x+n])
    40  				for i := 0; i < y; i++ {
    41  					if dst[i] != byte(i&127) {
    42  						t.Fatalf("prefix dst[%d] = %d", i, dst[i])
    43  					}
    44  				}
    45  				for i := y; i < y+n; i++ {
    46  					if dst[i] != byte(128+((i-y+x)&127)) {
    47  						t.Fatalf("copied dst[%d] = %d", i, dst[i])
    48  					}
    49  					dst[i] = byte(i & 127) // reset dst
    50  				}
    51  				for i := y + n; i < size; i++ {
    52  					if dst[i] != byte(i&127) {
    53  						t.Fatalf("suffix dst[%d] = %d", i, dst[i])
    54  					}
    55  				}
    56  			}
    57  		}
    58  	}
    59  }
    60  
    61  func TestMemmoveAlias(t *testing.T) {
    62  	if *flagQuick {
    63  		t.Skip("-quick")
    64  	}
    65  	t.Parallel()
    66  	size := 256
    67  	if testing.Short() {
    68  		size = 128 + 16
    69  	}
    70  	buf := make([]byte, size)
    71  	for i := 0; i < size; i++ {
    72  		buf[i] = byte(i)
    73  	}
    74  	for n := 0; n <= size; n++ {
    75  		for x := 0; x <= size-n; x++ { // src offset
    76  			for y := 0; y <= size-n; y++ { // dst offset
    77  				copy(buf[y:y+n], buf[x:x+n])
    78  				for i := 0; i < y; i++ {
    79  					if buf[i] != byte(i) {
    80  						t.Fatalf("prefix buf[%d] = %d", i, buf[i])
    81  					}
    82  				}
    83  				for i := y; i < y+n; i++ {
    84  					if buf[i] != byte(i-y+x) {
    85  						t.Fatalf("copied buf[%d] = %d", i, buf[i])
    86  					}
    87  					buf[i] = byte(i) // reset buf
    88  				}
    89  				for i := y + n; i < size; i++ {
    90  					if buf[i] != byte(i) {
    91  						t.Fatalf("suffix buf[%d] = %d", i, buf[i])
    92  					}
    93  				}
    94  			}
    95  		}
    96  	}
    97  }
    98  
    99  func TestMemmoveLarge0x180000(t *testing.T) {
   100  	if testing.Short() && testenv.Builder() == "" {
   101  		t.Skip("-short")
   102  	}
   103  
   104  	t.Parallel()
   105  	if race.Enabled {
   106  		t.Skip("skipping large memmove test under race detector")
   107  	}
   108  	testSize(t, 0x180000)
   109  }
   110  
   111  func TestMemmoveOverlapLarge0x120000(t *testing.T) {
   112  	if testing.Short() && testenv.Builder() == "" {
   113  		t.Skip("-short")
   114  	}
   115  
   116  	t.Parallel()
   117  	if race.Enabled {
   118  		t.Skip("skipping large memmove test under race detector")
   119  	}
   120  	testOverlap(t, 0x120000)
   121  }
   122  
   123  func testSize(t *testing.T, size int) {
   124  	src := make([]byte, size)
   125  	dst := make([]byte, size)
   126  	_, _ = rand.Read(src)
   127  	_, _ = rand.Read(dst)
   128  
   129  	ref := make([]byte, size)
   130  	copyref(ref, dst)
   131  
   132  	for n := size - 50; n > 1; n >>= 1 {
   133  		for x := 0; x <= size-n; x = x*7 + 1 { // offset in src
   134  			for y := 0; y <= size-n; y = y*9 + 1 { // offset in dst
   135  				copy(dst[y:y+n], src[x:x+n])
   136  				copyref(ref[y:y+n], src[x:x+n])
   137  				p := cmpb(dst, ref)
   138  				if p >= 0 {
   139  					t.Fatalf("Copy failed, copying from src[%d:%d] to dst[%d:%d].\nOffset %d is different, %v != %v", x, x+n, y, y+n, p, dst[p], ref[p])
   140  				}
   141  			}
   142  		}
   143  	}
   144  }
   145  
   146  func testOverlap(t *testing.T, size int) {
   147  	src := make([]byte, size)
   148  	test := make([]byte, size)
   149  	ref := make([]byte, size)
   150  	_, _ = rand.Read(src)
   151  
   152  	for n := size - 50; n > 1; n >>= 1 {
   153  		for x := 0; x <= size-n; x = x*7 + 1 { // offset in src
   154  			for y := 0; y <= size-n; y = y*9 + 1 { // offset in dst
   155  				// Reset input
   156  				copyref(test, src)
   157  				copyref(ref, src)
   158  				copy(test[y:y+n], test[x:x+n])
   159  				if y <= x {
   160  					copyref(ref[y:y+n], ref[x:x+n])
   161  				} else {
   162  					copybw(ref[y:y+n], ref[x:x+n])
   163  				}
   164  				p := cmpb(test, ref)
   165  				if p >= 0 {
   166  					t.Fatalf("Copy failed, copying from src[%d:%d] to dst[%d:%d].\nOffset %d is different, %v != %v", x, x+n, y, y+n, p, test[p], ref[p])
   167  				}
   168  			}
   169  		}
   170  	}
   171  
   172  }
   173  
   174  // Forward copy.
   175  func copyref(dst, src []byte) {
   176  	for i, v := range src {
   177  		dst[i] = v
   178  	}
   179  }
   180  
   181  // Backwards copy
   182  func copybw(dst, src []byte) {
   183  	if len(src) == 0 {
   184  		return
   185  	}
   186  	for i := len(src) - 1; i >= 0; i-- {
   187  		dst[i] = src[i]
   188  	}
   189  }
   190  
   191  // Returns offset of difference
   192  func matchLen(a, b []byte, max int) int {
   193  	a = a[:max]
   194  	b = b[:max]
   195  	for i, av := range a {
   196  		if b[i] != av {
   197  			return i
   198  		}
   199  	}
   200  	return max
   201  }
   202  
   203  func cmpb(a, b []byte) int {
   204  	l := matchLen(a, b, len(a))
   205  	if l == len(a) {
   206  		return -1
   207  	}
   208  	return l
   209  }
   210  
   211  // Ensure that memmove writes pointers atomically, so the GC won't
   212  // observe a partially updated pointer.
   213  func TestMemmoveAtomicity(t *testing.T) {
   214  	if race.Enabled {
   215  		t.Skip("skip under the race detector -- this test is intentionally racy")
   216  	}
   217  
   218  	var x int
   219  
   220  	for _, backward := range []bool{true, false} {
   221  		for _, n := range []int{3, 4, 5, 6, 7, 8, 9, 10, 15, 25, 49} {
   222  			n := n
   223  
   224  			// test copying [N]*int.
   225  			sz := uintptr(n * PtrSize)
   226  			name := fmt.Sprint(sz)
   227  			if backward {
   228  				name += "-backward"
   229  			} else {
   230  				name += "-forward"
   231  			}
   232  			t.Run(name, func(t *testing.T) {
   233  				// Use overlapping src and dst to force forward/backward copy.
   234  				var s [100]*int
   235  				src := s[n-1 : 2*n-1]
   236  				dst := s[:n]
   237  				if backward {
   238  					src, dst = dst, src
   239  				}
   240  				for i := range src {
   241  					src[i] = &x
   242  				}
   243  				for i := range dst {
   244  					dst[i] = nil
   245  				}
   246  
   247  				var ready atomic.Uint32
   248  				go func() {
   249  					sp := unsafe.Pointer(&src[0])
   250  					dp := unsafe.Pointer(&dst[0])
   251  					ready.Store(1)
   252  					for i := 0; i < 10000; i++ {
   253  						Memmove(dp, sp, sz)
   254  						MemclrNoHeapPointers(dp, sz)
   255  					}
   256  					ready.Store(2)
   257  				}()
   258  
   259  				for ready.Load() == 0 {
   260  					Gosched()
   261  				}
   262  
   263  				for ready.Load() != 2 {
   264  					for i := range dst {
   265  						p := dst[i]
   266  						if p != nil && p != &x {
   267  							t.Fatalf("got partially updated pointer %p at dst[%d], want either nil or %p", p, i, &x)
   268  						}
   269  					}
   270  				}
   271  			})
   272  		}
   273  	}
   274  }
   275  
   276  func benchmarkSizes(b *testing.B, sizes []int, fn func(b *testing.B, n int)) {
   277  	for _, n := range sizes {
   278  		b.Run(fmt.Sprint(n), func(b *testing.B) {
   279  			b.SetBytes(int64(n))
   280  			fn(b, n)
   281  		})
   282  	}
   283  }
   284  
   285  var bufSizes = []int{
   286  	0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
   287  	32, 64, 128, 256, 512, 1024, 2048, 4096,
   288  }
   289  var bufSizesOverlap = []int{
   290  	32, 64, 128, 256, 512, 1024, 2048, 4096,
   291  }
   292  
   293  func BenchmarkMemmove(b *testing.B) {
   294  	benchmarkSizes(b, bufSizes, func(b *testing.B, n int) {
   295  		x := make([]byte, n)
   296  		y := make([]byte, n)
   297  		for i := 0; i < b.N; i++ {
   298  			copy(x, y)
   299  		}
   300  	})
   301  }
   302  
   303  func BenchmarkMemmoveOverlap(b *testing.B) {
   304  	benchmarkSizes(b, bufSizesOverlap, func(b *testing.B, n int) {
   305  		x := make([]byte, n+16)
   306  		for i := 0; i < b.N; i++ {
   307  			copy(x[16:n+16], x[:n])
   308  		}
   309  	})
   310  }
   311  
   312  func BenchmarkMemmoveUnalignedDst(b *testing.B) {
   313  	benchmarkSizes(b, bufSizes, func(b *testing.B, n int) {
   314  		x := make([]byte, n+1)
   315  		y := make([]byte, n)
   316  		for i := 0; i < b.N; i++ {
   317  			copy(x[1:], y)
   318  		}
   319  	})
   320  }
   321  
   322  func BenchmarkMemmoveUnalignedDstOverlap(b *testing.B) {
   323  	benchmarkSizes(b, bufSizesOverlap, func(b *testing.B, n int) {
   324  		x := make([]byte, n+16)
   325  		for i := 0; i < b.N; i++ {
   326  			copy(x[16:n+16], x[1:n+1])
   327  		}
   328  	})
   329  }
   330  
   331  func BenchmarkMemmoveUnalignedSrc(b *testing.B) {
   332  	benchmarkSizes(b, bufSizes, func(b *testing.B, n int) {
   333  		x := make([]byte, n)
   334  		y := make([]byte, n+1)
   335  		for i := 0; i < b.N; i++ {
   336  			copy(x, y[1:])
   337  		}
   338  	})
   339  }
   340  
   341  func BenchmarkMemmoveUnalignedSrcDst(b *testing.B) {
   342  	for _, n := range []int{16, 64, 256, 4096, 65536} {
   343  		buf := make([]byte, (n+8)*2)
   344  		x := buf[:len(buf)/2]
   345  		y := buf[len(buf)/2:]
   346  		for _, off := range []int{0, 1, 4, 7} {
   347  			b.Run(fmt.Sprint("f_", n, off), func(b *testing.B) {
   348  				b.SetBytes(int64(n))
   349  				for i := 0; i < b.N; i++ {
   350  					copy(x[off:n+off], y[off:n+off])
   351  				}
   352  			})
   353  
   354  			b.Run(fmt.Sprint("b_", n, off), func(b *testing.B) {
   355  				b.SetBytes(int64(n))
   356  				for i := 0; i < b.N; i++ {
   357  					copy(y[off:n+off], x[off:n+off])
   358  				}
   359  			})
   360  		}
   361  	}
   362  }
   363  
   364  func BenchmarkMemmoveUnalignedSrcOverlap(b *testing.B) {
   365  	benchmarkSizes(b, bufSizesOverlap, func(b *testing.B, n int) {
   366  		x := make([]byte, n+1)
   367  		for i := 0; i < b.N; i++ {
   368  			copy(x[1:n+1], x[:n])
   369  		}
   370  	})
   371  }
   372  
   373  func TestMemclr(t *testing.T) {
   374  	size := 512
   375  	if testing.Short() {
   376  		size = 128 + 16
   377  	}
   378  	mem := make([]byte, size)
   379  	for i := 0; i < size; i++ {
   380  		mem[i] = 0xee
   381  	}
   382  	for n := 0; n < size; n++ {
   383  		for x := 0; x <= size-n; x++ { // offset in mem
   384  			MemclrBytes(mem[x : x+n])
   385  			for i := 0; i < x; i++ {
   386  				if mem[i] != 0xee {
   387  					t.Fatalf("overwrite prefix mem[%d] = %d", i, mem[i])
   388  				}
   389  			}
   390  			for i := x; i < x+n; i++ {
   391  				if mem[i] != 0 {
   392  					t.Fatalf("failed clear mem[%d] = %d", i, mem[i])
   393  				}
   394  				mem[i] = 0xee
   395  			}
   396  			for i := x + n; i < size; i++ {
   397  				if mem[i] != 0xee {
   398  					t.Fatalf("overwrite suffix mem[%d] = %d", i, mem[i])
   399  				}
   400  			}
   401  		}
   402  	}
   403  }
   404  
   405  func BenchmarkMemclr(b *testing.B) {
   406  	for _, n := range []int{5, 16, 64, 256, 4096, 65536} {
   407  		x := make([]byte, n)
   408  		b.Run(fmt.Sprint(n), func(b *testing.B) {
   409  			b.SetBytes(int64(n))
   410  			for i := 0; i < b.N; i++ {
   411  				MemclrBytes(x)
   412  			}
   413  		})
   414  	}
   415  	for _, m := range []int{1, 4, 8, 16, 64} {
   416  		x := make([]byte, m<<20)
   417  		b.Run(fmt.Sprint(m, "M"), func(b *testing.B) {
   418  			b.SetBytes(int64(m << 20))
   419  			for i := 0; i < b.N; i++ {
   420  				MemclrBytes(x)
   421  			}
   422  		})
   423  	}
   424  }
   425  
   426  func BenchmarkMemclrUnaligned(b *testing.B) {
   427  	for _, off := range []int{0, 1, 4, 7} {
   428  		for _, n := range []int{5, 16, 64, 256, 4096, 65536} {
   429  			x := make([]byte, n+off)
   430  			b.Run(fmt.Sprint(off, n), func(b *testing.B) {
   431  				b.SetBytes(int64(n))
   432  				for i := 0; i < b.N; i++ {
   433  					MemclrBytes(x[off:])
   434  				}
   435  			})
   436  		}
   437  	}
   438  
   439  	for _, off := range []int{0, 1, 4, 7} {
   440  		for _, m := range []int{1, 4, 8, 16, 64} {
   441  			x := make([]byte, (m<<20)+off)
   442  			b.Run(fmt.Sprint(off, m, "M"), func(b *testing.B) {
   443  				b.SetBytes(int64(m << 20))
   444  				for i := 0; i < b.N; i++ {
   445  					MemclrBytes(x[off:])
   446  				}
   447  			})
   448  		}
   449  	}
   450  }
   451  
   452  func BenchmarkGoMemclr(b *testing.B) {
   453  	benchmarkSizes(b, []int{5, 16, 64, 256}, func(b *testing.B, n int) {
   454  		x := make([]byte, n)
   455  		for i := 0; i < b.N; i++ {
   456  			for j := range x {
   457  				x[j] = 0
   458  			}
   459  		}
   460  	})
   461  }
   462  
   463  func BenchmarkMemclrRange(b *testing.B) {
   464  	type RunData struct {
   465  		data []int
   466  	}
   467  
   468  	benchSizes := []RunData{
   469  		{[]int{1043, 1078, 1894, 1582, 1044, 1165, 1467, 1100, 1919, 1562, 1932, 1645,
   470  			1412, 1038, 1576, 1200, 1029, 1336, 1095, 1494, 1350, 1025, 1502, 1548, 1316, 1296,
   471  			1868, 1639, 1546, 1626, 1642, 1308, 1726, 1665, 1678, 1187, 1515, 1598, 1353, 1237,
   472  			1977, 1452, 2012, 1914, 1514, 1136, 1975, 1618, 1536, 1695, 1600, 1733, 1392, 1099,
   473  			1358, 1996, 1224, 1783, 1197, 1838, 1460, 1556, 1554, 2020}}, // 1kb-2kb
   474  		{[]int{3964, 5139, 6573, 7775, 6553, 2413, 3466, 5394, 2469, 7336, 7091, 6745,
   475  			4028, 5643, 6164, 3475, 4138, 6908, 7559, 3335, 5660, 4122, 3945, 2082, 7564, 6584,
   476  			5111, 2288, 6789, 2797, 4928, 7986, 5163, 5447, 2999, 4968, 3174, 3202, 7908, 8137,
   477  			4735, 6161, 4646, 7592, 3083, 5329, 3687, 2754, 3599, 7231, 6455, 2549, 8063, 2189,
   478  			7121, 5048, 4277, 6626, 6306, 2815, 7473, 3963, 7549, 7255}}, // 2kb-8kb
   479  		{[]int{16304, 15936, 15760, 4736, 9136, 11184, 10160, 5952, 14560, 15744,
   480  			6624, 5872, 13088, 14656, 14192, 10304, 4112, 10384, 9344, 4496, 11392, 7024,
   481  			5200, 10064, 14784, 5808, 13504, 10480, 8512, 4896, 13264, 5600}}, // 4kb-16kb
   482  		{[]int{164576, 233136, 220224, 183280, 214112, 217248, 228560, 201728}}, // 128kb-256kb
   483  	}
   484  
   485  	for _, t := range benchSizes {
   486  		total := 0
   487  		minLen := 0
   488  		maxLen := 0
   489  
   490  		for _, clrLen := range t.data {
   491  			maxLen = max(maxLen, clrLen)
   492  			if clrLen < minLen || minLen == 0 {
   493  				minLen = clrLen
   494  			}
   495  			total += clrLen
   496  		}
   497  		buffer := make([]byte, maxLen)
   498  
   499  		text := ""
   500  		if minLen >= (1 << 20) {
   501  			text = fmt.Sprint(minLen>>20, "M ", (maxLen+(1<<20-1))>>20, "M")
   502  		} else if minLen >= (1 << 10) {
   503  			text = fmt.Sprint(minLen>>10, "K ", (maxLen+(1<<10-1))>>10, "K")
   504  		} else {
   505  			text = fmt.Sprint(minLen, " ", maxLen)
   506  		}
   507  		b.Run(text, func(b *testing.B) {
   508  			b.SetBytes(int64(total))
   509  			for i := 0; i < b.N; i++ {
   510  				for _, clrLen := range t.data {
   511  					MemclrBytes(buffer[:clrLen])
   512  				}
   513  			}
   514  		})
   515  	}
   516  }
   517  
   518  func BenchmarkClearFat7(b *testing.B) {
   519  	p := new([7]byte)
   520  	Escape(p)
   521  	b.ResetTimer()
   522  	for i := 0; i < b.N; i++ {
   523  		*p = [7]byte{}
   524  	}
   525  }
   526  
   527  func BenchmarkClearFat8(b *testing.B) {
   528  	p := new([8 / 4]uint32)
   529  	Escape(p)
   530  	b.ResetTimer()
   531  	for i := 0; i < b.N; i++ {
   532  		*p = [8 / 4]uint32{}
   533  	}
   534  }
   535  
   536  func BenchmarkClearFat11(b *testing.B) {
   537  	p := new([11]byte)
   538  	Escape(p)
   539  	b.ResetTimer()
   540  	for i := 0; i < b.N; i++ {
   541  		*p = [11]byte{}
   542  	}
   543  }
   544  
   545  func BenchmarkClearFat12(b *testing.B) {
   546  	p := new([12 / 4]uint32)
   547  	Escape(p)
   548  	b.ResetTimer()
   549  	for i := 0; i < b.N; i++ {
   550  		*p = [12 / 4]uint32{}
   551  	}
   552  }
   553  
   554  func BenchmarkClearFat13(b *testing.B) {
   555  	p := new([13]byte)
   556  	Escape(p)
   557  	b.ResetTimer()
   558  	for i := 0; i < b.N; i++ {
   559  		*p = [13]byte{}
   560  	}
   561  }
   562  
   563  func BenchmarkClearFat14(b *testing.B) {
   564  	p := new([14]byte)
   565  	Escape(p)
   566  	b.ResetTimer()
   567  	for i := 0; i < b.N; i++ {
   568  		*p = [14]byte{}
   569  	}
   570  }
   571  
   572  func BenchmarkClearFat15(b *testing.B) {
   573  	p := new([15]byte)
   574  	Escape(p)
   575  	b.ResetTimer()
   576  	for i := 0; i < b.N; i++ {
   577  		*p = [15]byte{}
   578  	}
   579  }
   580  
   581  func BenchmarkClearFat16(b *testing.B) {
   582  	p := new([16 / 4]uint32)
   583  	Escape(p)
   584  	b.ResetTimer()
   585  	for i := 0; i < b.N; i++ {
   586  		*p = [16 / 4]uint32{}
   587  	}
   588  }
   589  
   590  func BenchmarkClearFat24(b *testing.B) {
   591  	p := new([24 / 4]uint32)
   592  	Escape(p)
   593  	b.ResetTimer()
   594  	for i := 0; i < b.N; i++ {
   595  		*p = [24 / 4]uint32{}
   596  	}
   597  }
   598  
   599  func BenchmarkClearFat32(b *testing.B) {
   600  	p := new([32 / 4]uint32)
   601  	Escape(p)
   602  	b.ResetTimer()
   603  	for i := 0; i < b.N; i++ {
   604  		*p = [32 / 4]uint32{}
   605  	}
   606  }
   607  
   608  func BenchmarkClearFat40(b *testing.B) {
   609  	p := new([40 / 4]uint32)
   610  	Escape(p)
   611  	b.ResetTimer()
   612  	for i := 0; i < b.N; i++ {
   613  		*p = [40 / 4]uint32{}
   614  	}
   615  }
   616  
   617  func BenchmarkClearFat48(b *testing.B) {
   618  	p := new([48 / 4]uint32)
   619  	Escape(p)
   620  	b.ResetTimer()
   621  	for i := 0; i < b.N; i++ {
   622  		*p = [48 / 4]uint32{}
   623  	}
   624  }
   625  
   626  func BenchmarkClearFat56(b *testing.B) {
   627  	p := new([56 / 4]uint32)
   628  	Escape(p)
   629  	b.ResetTimer()
   630  	for i := 0; i < b.N; i++ {
   631  		*p = [56 / 4]uint32{}
   632  	}
   633  }
   634  
   635  func BenchmarkClearFat64(b *testing.B) {
   636  	p := new([64 / 4]uint32)
   637  	Escape(p)
   638  	b.ResetTimer()
   639  	for i := 0; i < b.N; i++ {
   640  		*p = [64 / 4]uint32{}
   641  	}
   642  }
   643  
   644  func BenchmarkClearFat72(b *testing.B) {
   645  	p := new([72 / 4]uint32)
   646  	Escape(p)
   647  	b.ResetTimer()
   648  	for i := 0; i < b.N; i++ {
   649  		*p = [72 / 4]uint32{}
   650  	}
   651  }
   652  
   653  func BenchmarkClearFat128(b *testing.B) {
   654  	p := new([128 / 4]uint32)
   655  	Escape(p)
   656  	b.ResetTimer()
   657  	for i := 0; i < b.N; i++ {
   658  		*p = [128 / 4]uint32{}
   659  	}
   660  }
   661  
   662  func BenchmarkClearFat256(b *testing.B) {
   663  	p := new([256 / 4]uint32)
   664  	Escape(p)
   665  	b.ResetTimer()
   666  	for i := 0; i < b.N; i++ {
   667  		*p = [256 / 4]uint32{}
   668  	}
   669  }
   670  
   671  func BenchmarkClearFat512(b *testing.B) {
   672  	p := new([512 / 4]uint32)
   673  	Escape(p)
   674  	b.ResetTimer()
   675  	for i := 0; i < b.N; i++ {
   676  		*p = [512 / 4]uint32{}
   677  	}
   678  }
   679  
   680  func BenchmarkClearFat1024(b *testing.B) {
   681  	p := new([1024 / 4]uint32)
   682  	Escape(p)
   683  	b.ResetTimer()
   684  	for i := 0; i < b.N; i++ {
   685  		*p = [1024 / 4]uint32{}
   686  	}
   687  }
   688  
   689  func BenchmarkClearFat1032(b *testing.B) {
   690  	p := new([1032 / 4]uint32)
   691  	Escape(p)
   692  	b.ResetTimer()
   693  	for i := 0; i < b.N; i++ {
   694  		*p = [1032 / 4]uint32{}
   695  	}
   696  }
   697  
   698  func BenchmarkClearFat1040(b *testing.B) {
   699  	p := new([1040 / 4]uint32)
   700  	Escape(p)
   701  	b.ResetTimer()
   702  	for i := 0; i < b.N; i++ {
   703  		*p = [1040 / 4]uint32{}
   704  	}
   705  }
   706  
   707  func BenchmarkCopyFat7(b *testing.B) {
   708  	var x [7]byte
   709  	p := new([7]byte)
   710  	Escape(p)
   711  	b.ResetTimer()
   712  	for i := 0; i < b.N; i++ {
   713  		*p = x
   714  	}
   715  }
   716  
   717  func BenchmarkCopyFat8(b *testing.B) {
   718  	var x [8 / 4]uint32
   719  	p := new([8 / 4]uint32)
   720  	Escape(p)
   721  	b.ResetTimer()
   722  	for i := 0; i < b.N; i++ {
   723  		*p = x
   724  	}
   725  }
   726  
   727  func BenchmarkCopyFat11(b *testing.B) {
   728  	var x [11]byte
   729  	p := new([11]byte)
   730  	Escape(p)
   731  	b.ResetTimer()
   732  	for i := 0; i < b.N; i++ {
   733  		*p = x
   734  	}
   735  }
   736  
   737  func BenchmarkCopyFat12(b *testing.B) {
   738  	var x [12 / 4]uint32
   739  	p := new([12 / 4]uint32)
   740  	Escape(p)
   741  	b.ResetTimer()
   742  	for i := 0; i < b.N; i++ {
   743  		*p = x
   744  	}
   745  }
   746  
   747  func BenchmarkCopyFat13(b *testing.B) {
   748  	var x [13]byte
   749  	p := new([13]byte)
   750  	Escape(p)
   751  	b.ResetTimer()
   752  	for i := 0; i < b.N; i++ {
   753  		*p = x
   754  	}
   755  }
   756  
   757  func BenchmarkCopyFat14(b *testing.B) {
   758  	var x [14]byte
   759  	p := new([14]byte)
   760  	Escape(p)
   761  	b.ResetTimer()
   762  	for i := 0; i < b.N; i++ {
   763  		*p = x
   764  	}
   765  }
   766  
   767  func BenchmarkCopyFat15(b *testing.B) {
   768  	var x [15]byte
   769  	p := new([15]byte)
   770  	Escape(p)
   771  	b.ResetTimer()
   772  	for i := 0; i < b.N; i++ {
   773  		*p = x
   774  	}
   775  }
   776  
   777  func BenchmarkCopyFat16(b *testing.B) {
   778  	var x [16 / 4]uint32
   779  	p := new([16 / 4]uint32)
   780  	Escape(p)
   781  	b.ResetTimer()
   782  	for i := 0; i < b.N; i++ {
   783  		*p = x
   784  	}
   785  }
   786  
   787  func BenchmarkCopyFat24(b *testing.B) {
   788  	var x [24 / 4]uint32
   789  	p := new([24 / 4]uint32)
   790  	Escape(p)
   791  	b.ResetTimer()
   792  	for i := 0; i < b.N; i++ {
   793  		*p = x
   794  	}
   795  }
   796  
   797  func BenchmarkCopyFat32(b *testing.B) {
   798  	var x [32 / 4]uint32
   799  	p := new([32 / 4]uint32)
   800  	Escape(p)
   801  	b.ResetTimer()
   802  	for i := 0; i < b.N; i++ {
   803  		*p = x
   804  	}
   805  }
   806  
   807  func BenchmarkCopyFat64(b *testing.B) {
   808  	var x [64 / 4]uint32
   809  	p := new([64 / 4]uint32)
   810  	Escape(p)
   811  	b.ResetTimer()
   812  	for i := 0; i < b.N; i++ {
   813  		*p = x
   814  	}
   815  }
   816  
   817  func BenchmarkCopyFat72(b *testing.B) {
   818  	var x [72 / 4]uint32
   819  	p := new([72 / 4]uint32)
   820  	Escape(p)
   821  	b.ResetTimer()
   822  	for i := 0; i < b.N; i++ {
   823  		*p = x
   824  	}
   825  }
   826  
   827  func BenchmarkCopyFat128(b *testing.B) {
   828  	var x [128 / 4]uint32
   829  	p := new([128 / 4]uint32)
   830  	Escape(p)
   831  	b.ResetTimer()
   832  	for i := 0; i < b.N; i++ {
   833  		*p = x
   834  	}
   835  }
   836  
   837  func BenchmarkCopyFat256(b *testing.B) {
   838  	var x [256 / 4]uint32
   839  	p := new([256 / 4]uint32)
   840  	Escape(p)
   841  	b.ResetTimer()
   842  	for i := 0; i < b.N; i++ {
   843  		*p = x
   844  	}
   845  }
   846  
   847  func BenchmarkCopyFat512(b *testing.B) {
   848  	var x [512 / 4]uint32
   849  	p := new([512 / 4]uint32)
   850  	Escape(p)
   851  	b.ResetTimer()
   852  	for i := 0; i < b.N; i++ {
   853  		*p = x
   854  	}
   855  }
   856  
   857  func BenchmarkCopyFat520(b *testing.B) {
   858  	var x [520 / 4]uint32
   859  	p := new([520 / 4]uint32)
   860  	Escape(p)
   861  	b.ResetTimer()
   862  	for i := 0; i < b.N; i++ {
   863  		*p = x
   864  	}
   865  }
   866  
   867  func BenchmarkCopyFat1024(b *testing.B) {
   868  	var x [1024 / 4]uint32
   869  	p := new([1024 / 4]uint32)
   870  	Escape(p)
   871  	b.ResetTimer()
   872  	for i := 0; i < b.N; i++ {
   873  		*p = x
   874  	}
   875  }
   876  
   877  func BenchmarkCopyFat1032(b *testing.B) {
   878  	var x [1032 / 4]uint32
   879  	p := new([1032 / 4]uint32)
   880  	Escape(p)
   881  	b.ResetTimer()
   882  	for i := 0; i < b.N; i++ {
   883  		*p = x
   884  	}
   885  }
   886  
   887  func BenchmarkCopyFat1040(b *testing.B) {
   888  	var x [1040 / 4]uint32
   889  	p := new([1040 / 4]uint32)
   890  	Escape(p)
   891  	b.ResetTimer()
   892  	for i := 0; i < b.N; i++ {
   893  		*p = x
   894  	}
   895  }
   896  
   897  // BenchmarkIssue18740 ensures that memmove uses 4 and 8 byte load/store to move 4 and 8 bytes.
   898  // It used to do 2 2-byte load/stores, which leads to a pipeline stall
   899  // when we try to read the result with one 4-byte load.
   900  func BenchmarkIssue18740(b *testing.B) {
   901  	benchmarks := []struct {
   902  		name  string
   903  		nbyte int
   904  		f     func([]byte) uint64
   905  	}{
   906  		{"2byte", 2, func(buf []byte) uint64 { return uint64(binary.LittleEndian.Uint16(buf)) }},
   907  		{"4byte", 4, func(buf []byte) uint64 { return uint64(binary.LittleEndian.Uint32(buf)) }},
   908  		{"8byte", 8, func(buf []byte) uint64 { return binary.LittleEndian.Uint64(buf) }},
   909  	}
   910  
   911  	var g [4096]byte
   912  	for _, bm := range benchmarks {
   913  		buf := make([]byte, bm.nbyte)
   914  		b.Run(bm.name, func(b *testing.B) {
   915  			for j := 0; j < b.N; j++ {
   916  				for i := 0; i < 4096; i += bm.nbyte {
   917  					copy(buf[:], g[i:])
   918  					sink += bm.f(buf[:])
   919  				}
   920  			}
   921  		})
   922  	}
   923  }
   924  
   925  var memclrSink []int8
   926  
   927  func BenchmarkMemclrKnownSize1(b *testing.B) {
   928  	var x [1]int8
   929  
   930  	b.SetBytes(1)
   931  	for i := 0; i < b.N; i++ {
   932  		for a := range x {
   933  			x[a] = 0
   934  		}
   935  	}
   936  
   937  	memclrSink = x[:]
   938  }
   939  func BenchmarkMemclrKnownSize2(b *testing.B) {
   940  	var x [2]int8
   941  
   942  	b.SetBytes(2)
   943  	for i := 0; i < b.N; i++ {
   944  		for a := range x {
   945  			x[a] = 0
   946  		}
   947  	}
   948  
   949  	memclrSink = x[:]
   950  }
   951  func BenchmarkMemclrKnownSize4(b *testing.B) {
   952  	var x [4]int8
   953  
   954  	b.SetBytes(4)
   955  	for i := 0; i < b.N; i++ {
   956  		for a := range x {
   957  			x[a] = 0
   958  		}
   959  	}
   960  
   961  	memclrSink = x[:]
   962  }
   963  func BenchmarkMemclrKnownSize8(b *testing.B) {
   964  	var x [8]int8
   965  
   966  	b.SetBytes(8)
   967  	for i := 0; i < b.N; i++ {
   968  		for a := range x {
   969  			x[a] = 0
   970  		}
   971  	}
   972  
   973  	memclrSink = x[:]
   974  }
   975  func BenchmarkMemclrKnownSize16(b *testing.B) {
   976  	var x [16]int8
   977  
   978  	b.SetBytes(16)
   979  	for i := 0; i < b.N; i++ {
   980  		for a := range x {
   981  			x[a] = 0
   982  		}
   983  	}
   984  
   985  	memclrSink = x[:]
   986  }
   987  func BenchmarkMemclrKnownSize32(b *testing.B) {
   988  	var x [32]int8
   989  
   990  	b.SetBytes(32)
   991  	for i := 0; i < b.N; i++ {
   992  		for a := range x {
   993  			x[a] = 0
   994  		}
   995  	}
   996  
   997  	memclrSink = x[:]
   998  }
   999  func BenchmarkMemclrKnownSize64(b *testing.B) {
  1000  	var x [64]int8
  1001  
  1002  	b.SetBytes(64)
  1003  	for i := 0; i < b.N; i++ {
  1004  		for a := range x {
  1005  			x[a] = 0
  1006  		}
  1007  	}
  1008  
  1009  	memclrSink = x[:]
  1010  }
  1011  func BenchmarkMemclrKnownSize112(b *testing.B) {
  1012  	var x [112]int8
  1013  
  1014  	b.SetBytes(112)
  1015  	for i := 0; i < b.N; i++ {
  1016  		for a := range x {
  1017  			x[a] = 0
  1018  		}
  1019  	}
  1020  
  1021  	memclrSink = x[:]
  1022  }
  1023  
  1024  func BenchmarkMemclrKnownSize128(b *testing.B) {
  1025  	var x [128]int8
  1026  
  1027  	b.SetBytes(128)
  1028  	for i := 0; i < b.N; i++ {
  1029  		for a := range x {
  1030  			x[a] = 0
  1031  		}
  1032  	}
  1033  
  1034  	memclrSink = x[:]
  1035  }
  1036  
  1037  func BenchmarkMemclrKnownSize192(b *testing.B) {
  1038  	var x [192]int8
  1039  
  1040  	b.SetBytes(192)
  1041  	for i := 0; i < b.N; i++ {
  1042  		for a := range x {
  1043  			x[a] = 0
  1044  		}
  1045  	}
  1046  
  1047  	memclrSink = x[:]
  1048  }
  1049  
  1050  func BenchmarkMemclrKnownSize248(b *testing.B) {
  1051  	var x [248]int8
  1052  
  1053  	b.SetBytes(248)
  1054  	for i := 0; i < b.N; i++ {
  1055  		for a := range x {
  1056  			x[a] = 0
  1057  		}
  1058  	}
  1059  
  1060  	memclrSink = x[:]
  1061  }
  1062  
  1063  func BenchmarkMemclrKnownSize256(b *testing.B) {
  1064  	var x [256]int8
  1065  
  1066  	b.SetBytes(256)
  1067  	for i := 0; i < b.N; i++ {
  1068  		for a := range x {
  1069  			x[a] = 0
  1070  		}
  1071  	}
  1072  
  1073  	memclrSink = x[:]
  1074  }
  1075  func BenchmarkMemclrKnownSize512(b *testing.B) {
  1076  	var x [512]int8
  1077  
  1078  	b.SetBytes(512)
  1079  	for i := 0; i < b.N; i++ {
  1080  		for a := range x {
  1081  			x[a] = 0
  1082  		}
  1083  	}
  1084  
  1085  	memclrSink = x[:]
  1086  }
  1087  func BenchmarkMemclrKnownSize1024(b *testing.B) {
  1088  	var x [1024]int8
  1089  
  1090  	b.SetBytes(1024)
  1091  	for i := 0; i < b.N; i++ {
  1092  		for a := range x {
  1093  			x[a] = 0
  1094  		}
  1095  	}
  1096  
  1097  	memclrSink = x[:]
  1098  }
  1099  func BenchmarkMemclrKnownSize4096(b *testing.B) {
  1100  	var x [4096]int8
  1101  
  1102  	b.SetBytes(4096)
  1103  	for i := 0; i < b.N; i++ {
  1104  		for a := range x {
  1105  			x[a] = 0
  1106  		}
  1107  	}
  1108  
  1109  	memclrSink = x[:]
  1110  }
  1111  func BenchmarkMemclrKnownSize512KiB(b *testing.B) {
  1112  	var x [524288]int8
  1113  
  1114  	b.SetBytes(524288)
  1115  	for i := 0; i < b.N; i++ {
  1116  		for a := range x {
  1117  			x[a] = 0
  1118  		}
  1119  	}
  1120  
  1121  	memclrSink = x[:]
  1122  }
  1123  

View as plain text