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

View as plain text