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  			n := n
   225  
   226  			// test copying [N]*int.
   227  			sz := uintptr(n * PtrSize)
   228  			name := fmt.Sprint(sz)
   229  			if backward {
   230  				name += "-backward"
   231  			} else {
   232  				name += "-forward"
   233  			}
   234  			t.Run(name, func(t *testing.T) {
   235  				// Use overlapping src and dst to force forward/backward copy.
   236  				var s [100]*int
   237  				src := s[n-1 : 2*n-1]
   238  				dst := s[:n]
   239  				if backward {
   240  					src, dst = dst, src
   241  				}
   242  				for i := range src {
   243  					src[i] = &x
   244  				}
   245  				clear(dst)
   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  		b.ResetTimer()
   298  		for i := 0; i < b.N; i++ {
   299  			copy(x, y)
   300  		}
   301  	})
   302  }
   303  
   304  func BenchmarkMemmoveOverlap(b *testing.B) {
   305  	benchmarkSizes(b, bufSizesOverlap, func(b *testing.B, n int) {
   306  		x := make([]byte, n+16)
   307  		b.ResetTimer()
   308  		for i := 0; i < b.N; i++ {
   309  			copy(x[16:n+16], x[:n])
   310  		}
   311  	})
   312  }
   313  
   314  func BenchmarkMemmoveUnalignedDst(b *testing.B) {
   315  	benchmarkSizes(b, bufSizes, func(b *testing.B, n int) {
   316  		x := make([]byte, n+1)
   317  		y := make([]byte, n)
   318  		b.ResetTimer()
   319  		for i := 0; i < b.N; i++ {
   320  			copy(x[1:], y)
   321  		}
   322  	})
   323  }
   324  
   325  func BenchmarkMemmoveUnalignedDstOverlap(b *testing.B) {
   326  	benchmarkSizes(b, bufSizesOverlap, func(b *testing.B, n int) {
   327  		x := make([]byte, n+16)
   328  		b.ResetTimer()
   329  		for i := 0; i < b.N; i++ {
   330  			copy(x[16:n+16], x[1:n+1])
   331  		}
   332  	})
   333  }
   334  
   335  func BenchmarkMemmoveUnalignedSrc(b *testing.B) {
   336  	benchmarkSizes(b, bufSizes, func(b *testing.B, n int) {
   337  		x := make([]byte, n)
   338  		y := make([]byte, n+1)
   339  		b.ResetTimer()
   340  		for i := 0; i < b.N; i++ {
   341  			copy(x, y[1:])
   342  		}
   343  	})
   344  }
   345  
   346  func BenchmarkMemmoveUnalignedSrcDst(b *testing.B) {
   347  	for _, n := range []int{16, 64, 256, 4096, 65536} {
   348  		buf := make([]byte, (n+8)*2)
   349  		x := buf[:len(buf)/2]
   350  		y := buf[len(buf)/2:]
   351  		for _, off := range []int{0, 1, 4, 7} {
   352  			b.Run(fmt.Sprint("f_", n, off), func(b *testing.B) {
   353  				b.SetBytes(int64(n))
   354  				for i := 0; i < b.N; i++ {
   355  					copy(x[off:n+off], y[off:n+off])
   356  				}
   357  			})
   358  
   359  			b.Run(fmt.Sprint("b_", n, off), func(b *testing.B) {
   360  				b.SetBytes(int64(n))
   361  				for i := 0; i < b.N; i++ {
   362  					copy(y[off:n+off], x[off:n+off])
   363  				}
   364  			})
   365  		}
   366  	}
   367  }
   368  
   369  func BenchmarkMemmoveUnalignedSrcOverlap(b *testing.B) {
   370  	benchmarkSizes(b, bufSizesOverlap, func(b *testing.B, n int) {
   371  		x := make([]byte, n+1)
   372  		b.ResetTimer()
   373  		for i := 0; i < b.N; i++ {
   374  			copy(x[1:n+1], x[:n])
   375  		}
   376  	})
   377  }
   378  
   379  func TestMemclr(t *testing.T) {
   380  	size := 512
   381  	if testing.Short() {
   382  		size = 128 + 16
   383  	}
   384  	mem := make([]byte, size)
   385  	for i := 0; i < size; i++ {
   386  		mem[i] = 0xee
   387  	}
   388  	for n := 0; n < size; n++ {
   389  		for x := 0; x <= size-n; x++ { // offset in mem
   390  			MemclrBytes(mem[x : x+n])
   391  			for i := 0; i < x; i++ {
   392  				if mem[i] != 0xee {
   393  					t.Fatalf("overwrite prefix mem[%d] = %d", i, mem[i])
   394  				}
   395  			}
   396  			for i := x; i < x+n; i++ {
   397  				if mem[i] != 0 {
   398  					t.Fatalf("failed clear mem[%d] = %d", i, mem[i])
   399  				}
   400  				mem[i] = 0xee
   401  			}
   402  			for i := x + n; i < size; i++ {
   403  				if mem[i] != 0xee {
   404  					t.Fatalf("overwrite suffix mem[%d] = %d", i, mem[i])
   405  				}
   406  			}
   407  		}
   408  	}
   409  }
   410  
   411  func BenchmarkMemclr(b *testing.B) {
   412  	for _, n := range []int{5, 16, 64, 256, 4096, 65536} {
   413  		x := make([]byte, n)
   414  		b.Run(fmt.Sprint(n), func(b *testing.B) {
   415  			b.SetBytes(int64(n))
   416  			for i := 0; i < b.N; i++ {
   417  				MemclrBytes(x)
   418  			}
   419  		})
   420  	}
   421  	for _, m := range []int{1, 4, 8, 16, 64} {
   422  		x := make([]byte, m<<20)
   423  		b.Run(fmt.Sprint(m, "M"), func(b *testing.B) {
   424  			b.SetBytes(int64(m << 20))
   425  			for i := 0; i < b.N; i++ {
   426  				MemclrBytes(x)
   427  			}
   428  		})
   429  	}
   430  }
   431  
   432  func BenchmarkMemclrUnaligned(b *testing.B) {
   433  	for _, off := range []int{0, 1, 4, 7} {
   434  		for _, n := range []int{5, 16, 64, 256, 4096, 65536} {
   435  			x := make([]byte, n+off)
   436  			b.Run(fmt.Sprint(off, n), func(b *testing.B) {
   437  				b.SetBytes(int64(n))
   438  				for i := 0; i < b.N; i++ {
   439  					MemclrBytes(x[off:])
   440  				}
   441  			})
   442  		}
   443  	}
   444  
   445  	for _, off := range []int{0, 1, 4, 7} {
   446  		for _, m := range []int{1, 4, 8, 16, 64} {
   447  			x := make([]byte, (m<<20)+off)
   448  			b.Run(fmt.Sprint(off, m, "M"), func(b *testing.B) {
   449  				b.SetBytes(int64(m << 20))
   450  				for i := 0; i < b.N; i++ {
   451  					MemclrBytes(x[off:])
   452  				}
   453  			})
   454  		}
   455  	}
   456  }
   457  
   458  func BenchmarkGoMemclr(b *testing.B) {
   459  	benchmarkSizes(b, []int{5, 16, 64, 256}, func(b *testing.B, n int) {
   460  		x := make([]byte, n)
   461  		b.ResetTimer()
   462  		for i := 0; i < b.N; i++ {
   463  			clear(x)
   464  		}
   465  	})
   466  }
   467  
   468  func BenchmarkMemclrRange(b *testing.B) {
   469  	type RunData struct {
   470  		data []int
   471  	}
   472  
   473  	benchSizes := []RunData{
   474  		{[]int{1043, 1078, 1894, 1582, 1044, 1165, 1467, 1100, 1919, 1562, 1932, 1645,
   475  			1412, 1038, 1576, 1200, 1029, 1336, 1095, 1494, 1350, 1025, 1502, 1548, 1316, 1296,
   476  			1868, 1639, 1546, 1626, 1642, 1308, 1726, 1665, 1678, 1187, 1515, 1598, 1353, 1237,
   477  			1977, 1452, 2012, 1914, 1514, 1136, 1975, 1618, 1536, 1695, 1600, 1733, 1392, 1099,
   478  			1358, 1996, 1224, 1783, 1197, 1838, 1460, 1556, 1554, 2020}}, // 1kb-2kb
   479  		{[]int{3964, 5139, 6573, 7775, 6553, 2413, 3466, 5394, 2469, 7336, 7091, 6745,
   480  			4028, 5643, 6164, 3475, 4138, 6908, 7559, 3335, 5660, 4122, 3945, 2082, 7564, 6584,
   481  			5111, 2288, 6789, 2797, 4928, 7986, 5163, 5447, 2999, 4968, 3174, 3202, 7908, 8137,
   482  			4735, 6161, 4646, 7592, 3083, 5329, 3687, 2754, 3599, 7231, 6455, 2549, 8063, 2189,
   483  			7121, 5048, 4277, 6626, 6306, 2815, 7473, 3963, 7549, 7255}}, // 2kb-8kb
   484  		{[]int{16304, 15936, 15760, 4736, 9136, 11184, 10160, 5952, 14560, 15744,
   485  			6624, 5872, 13088, 14656, 14192, 10304, 4112, 10384, 9344, 4496, 11392, 7024,
   486  			5200, 10064, 14784, 5808, 13504, 10480, 8512, 4896, 13264, 5600}}, // 4kb-16kb
   487  		{[]int{164576, 233136, 220224, 183280, 214112, 217248, 228560, 201728}}, // 128kb-256kb
   488  	}
   489  
   490  	for _, t := range benchSizes {
   491  		total := 0
   492  		minLen := 0
   493  		maxLen := 0
   494  
   495  		for _, clrLen := range t.data {
   496  			maxLen = max(maxLen, clrLen)
   497  			if clrLen < minLen || minLen == 0 {
   498  				minLen = clrLen
   499  			}
   500  			total += clrLen
   501  		}
   502  		buffer := make([]byte, maxLen)
   503  
   504  		text := ""
   505  		if minLen >= (1 << 20) {
   506  			text = fmt.Sprint(minLen>>20, "M ", (maxLen+(1<<20-1))>>20, "M")
   507  		} else if minLen >= (1 << 10) {
   508  			text = fmt.Sprint(minLen>>10, "K ", (maxLen+(1<<10-1))>>10, "K")
   509  		} else {
   510  			text = fmt.Sprint(minLen, " ", maxLen)
   511  		}
   512  		b.Run(text, func(b *testing.B) {
   513  			b.SetBytes(int64(total))
   514  			for i := 0; i < b.N; i++ {
   515  				for _, clrLen := range t.data {
   516  					MemclrBytes(buffer[:clrLen])
   517  				}
   518  			}
   519  		})
   520  	}
   521  }
   522  
   523  func BenchmarkClearFat3(b *testing.B) {
   524  	p := new([3]byte)
   525  	Escape(p)
   526  	b.ResetTimer()
   527  	for i := 0; i < b.N; i++ {
   528  		*p = [3]byte{}
   529  	}
   530  }
   531  
   532  func BenchmarkClearFat4(b *testing.B) {
   533  	p := new([4 / 4]uint32)
   534  	Escape(p)
   535  	b.ResetTimer()
   536  	for i := 0; i < b.N; i++ {
   537  		*p = [4 / 4]uint32{}
   538  	}
   539  }
   540  
   541  func BenchmarkClearFat5(b *testing.B) {
   542  	p := new([5]byte)
   543  	Escape(p)
   544  	b.ResetTimer()
   545  	for i := 0; i < b.N; i++ {
   546  		*p = [5]byte{}
   547  	}
   548  }
   549  
   550  func BenchmarkClearFat6(b *testing.B) {
   551  	p := new([6]byte)
   552  	Escape(p)
   553  	b.ResetTimer()
   554  	for i := 0; i < b.N; i++ {
   555  		*p = [6]byte{}
   556  	}
   557  }
   558  
   559  func BenchmarkClearFat7(b *testing.B) {
   560  	p := new([7]byte)
   561  	Escape(p)
   562  	b.ResetTimer()
   563  	for i := 0; i < b.N; i++ {
   564  		*p = [7]byte{}
   565  	}
   566  }
   567  
   568  func BenchmarkClearFat8(b *testing.B) {
   569  	p := new([8 / 4]uint32)
   570  	Escape(p)
   571  	b.ResetTimer()
   572  	for i := 0; i < b.N; i++ {
   573  		*p = [8 / 4]uint32{}
   574  	}
   575  }
   576  
   577  func BenchmarkClearFat9(b *testing.B) {
   578  	p := new([9]byte)
   579  	Escape(p)
   580  	b.ResetTimer()
   581  	for i := 0; i < b.N; i++ {
   582  		*p = [9]byte{}
   583  	}
   584  }
   585  
   586  func BenchmarkClearFat10(b *testing.B) {
   587  	p := new([10]byte)
   588  	Escape(p)
   589  	b.ResetTimer()
   590  	for i := 0; i < b.N; i++ {
   591  		*p = [10]byte{}
   592  	}
   593  }
   594  
   595  func BenchmarkClearFat11(b *testing.B) {
   596  	p := new([11]byte)
   597  	Escape(p)
   598  	b.ResetTimer()
   599  	for i := 0; i < b.N; i++ {
   600  		*p = [11]byte{}
   601  	}
   602  }
   603  
   604  func BenchmarkClearFat12(b *testing.B) {
   605  	p := new([12 / 4]uint32)
   606  	Escape(p)
   607  	b.ResetTimer()
   608  	for i := 0; i < b.N; i++ {
   609  		*p = [12 / 4]uint32{}
   610  	}
   611  }
   612  
   613  func BenchmarkClearFat13(b *testing.B) {
   614  	p := new([13]byte)
   615  	Escape(p)
   616  	b.ResetTimer()
   617  	for i := 0; i < b.N; i++ {
   618  		*p = [13]byte{}
   619  	}
   620  }
   621  
   622  func BenchmarkClearFat14(b *testing.B) {
   623  	p := new([14]byte)
   624  	Escape(p)
   625  	b.ResetTimer()
   626  	for i := 0; i < b.N; i++ {
   627  		*p = [14]byte{}
   628  	}
   629  }
   630  
   631  func BenchmarkClearFat15(b *testing.B) {
   632  	p := new([15]byte)
   633  	Escape(p)
   634  	b.ResetTimer()
   635  	for i := 0; i < b.N; i++ {
   636  		*p = [15]byte{}
   637  	}
   638  }
   639  
   640  func BenchmarkClearFat16(b *testing.B) {
   641  	p := new([16 / 4]uint32)
   642  	Escape(p)
   643  	b.ResetTimer()
   644  	for i := 0; i < b.N; i++ {
   645  		*p = [16 / 4]uint32{}
   646  	}
   647  }
   648  
   649  func BenchmarkClearFat18(b *testing.B) {
   650  	p := new([18]byte)
   651  	Escape(p)
   652  	b.ResetTimer()
   653  	for i := 0; i < b.N; i++ {
   654  		*p = [18]byte{}
   655  	}
   656  }
   657  
   658  func BenchmarkClearFat20(b *testing.B) {
   659  	p := new([20 / 4]uint32)
   660  	Escape(p)
   661  	b.ResetTimer()
   662  	for i := 0; i < b.N; i++ {
   663  		*p = [20 / 4]uint32{}
   664  	}
   665  }
   666  
   667  func BenchmarkClearFat24(b *testing.B) {
   668  	p := new([24 / 4]uint32)
   669  	Escape(p)
   670  	b.ResetTimer()
   671  	for i := 0; i < b.N; i++ {
   672  		*p = [24 / 4]uint32{}
   673  	}
   674  }
   675  
   676  func BenchmarkClearFat32(b *testing.B) {
   677  	p := new([32 / 4]uint32)
   678  	Escape(p)
   679  	b.ResetTimer()
   680  	for i := 0; i < b.N; i++ {
   681  		*p = [32 / 4]uint32{}
   682  	}
   683  }
   684  
   685  func BenchmarkClearFat40(b *testing.B) {
   686  	p := new([40 / 4]uint32)
   687  	Escape(p)
   688  	b.ResetTimer()
   689  	for i := 0; i < b.N; i++ {
   690  		*p = [40 / 4]uint32{}
   691  	}
   692  }
   693  
   694  func BenchmarkClearFat48(b *testing.B) {
   695  	p := new([48 / 4]uint32)
   696  	Escape(p)
   697  	b.ResetTimer()
   698  	for i := 0; i < b.N; i++ {
   699  		*p = [48 / 4]uint32{}
   700  	}
   701  }
   702  
   703  func BenchmarkClearFat56(b *testing.B) {
   704  	p := new([56 / 4]uint32)
   705  	Escape(p)
   706  	b.ResetTimer()
   707  	for i := 0; i < b.N; i++ {
   708  		*p = [56 / 4]uint32{}
   709  	}
   710  }
   711  
   712  func BenchmarkClearFat64(b *testing.B) {
   713  	p := new([64 / 4]uint32)
   714  	Escape(p)
   715  	b.ResetTimer()
   716  	for i := 0; i < b.N; i++ {
   717  		*p = [64 / 4]uint32{}
   718  	}
   719  }
   720  
   721  func BenchmarkClearFat72(b *testing.B) {
   722  	p := new([72 / 4]uint32)
   723  	Escape(p)
   724  	b.ResetTimer()
   725  	for i := 0; i < b.N; i++ {
   726  		*p = [72 / 4]uint32{}
   727  	}
   728  }
   729  
   730  func BenchmarkClearFat128(b *testing.B) {
   731  	p := new([128 / 4]uint32)
   732  	Escape(p)
   733  	b.ResetTimer()
   734  	for i := 0; i < b.N; i++ {
   735  		*p = [128 / 4]uint32{}
   736  	}
   737  }
   738  
   739  func BenchmarkClearFat256(b *testing.B) {
   740  	p := new([256 / 4]uint32)
   741  	Escape(p)
   742  	b.ResetTimer()
   743  	for i := 0; i < b.N; i++ {
   744  		*p = [256 / 4]uint32{}
   745  	}
   746  }
   747  
   748  func BenchmarkClearFat512(b *testing.B) {
   749  	p := new([512 / 4]uint32)
   750  	Escape(p)
   751  	b.ResetTimer()
   752  	for i := 0; i < b.N; i++ {
   753  		*p = [512 / 4]uint32{}
   754  	}
   755  }
   756  
   757  func BenchmarkClearFat1024(b *testing.B) {
   758  	p := new([1024 / 4]uint32)
   759  	Escape(p)
   760  	b.ResetTimer()
   761  	for i := 0; i < b.N; i++ {
   762  		*p = [1024 / 4]uint32{}
   763  	}
   764  }
   765  
   766  func BenchmarkClearFat1032(b *testing.B) {
   767  	p := new([1032 / 4]uint32)
   768  	Escape(p)
   769  	b.ResetTimer()
   770  	for i := 0; i < b.N; i++ {
   771  		*p = [1032 / 4]uint32{}
   772  	}
   773  }
   774  
   775  func BenchmarkClearFat1040(b *testing.B) {
   776  	p := new([1040 / 4]uint32)
   777  	Escape(p)
   778  	b.ResetTimer()
   779  	for i := 0; i < b.N; i++ {
   780  		*p = [1040 / 4]uint32{}
   781  	}
   782  }
   783  
   784  func BenchmarkCopyFat3(b *testing.B) {
   785  	var x [3]byte
   786  	p := new([3]byte)
   787  	Escape(p)
   788  	b.ResetTimer()
   789  	for i := 0; i < b.N; i++ {
   790  		*p = x
   791  	}
   792  }
   793  
   794  func BenchmarkCopyFat4(b *testing.B) {
   795  	var x [4 / 4]uint32
   796  	p := new([4 / 4]uint32)
   797  	Escape(p)
   798  	b.ResetTimer()
   799  	for i := 0; i < b.N; i++ {
   800  		*p = x
   801  	}
   802  }
   803  
   804  func BenchmarkCopyFat5(b *testing.B) {
   805  	var x [5]byte
   806  	p := new([5]byte)
   807  	Escape(p)
   808  	b.ResetTimer()
   809  	for i := 0; i < b.N; i++ {
   810  		*p = x
   811  	}
   812  }
   813  
   814  func BenchmarkCopyFat6(b *testing.B) {
   815  	var x [6]byte
   816  	p := new([6]byte)
   817  	Escape(p)
   818  	b.ResetTimer()
   819  	for i := 0; i < b.N; i++ {
   820  		*p = x
   821  	}
   822  }
   823  
   824  func BenchmarkCopyFat7(b *testing.B) {
   825  	var x [7]byte
   826  	p := new([7]byte)
   827  	Escape(p)
   828  	b.ResetTimer()
   829  	for i := 0; i < b.N; i++ {
   830  		*p = x
   831  	}
   832  }
   833  
   834  func BenchmarkCopyFat8(b *testing.B) {
   835  	var x [8 / 4]uint32
   836  	p := new([8 / 4]uint32)
   837  	Escape(p)
   838  	b.ResetTimer()
   839  	for i := 0; i < b.N; i++ {
   840  		*p = x
   841  	}
   842  }
   843  
   844  func BenchmarkCopyFat9(b *testing.B) {
   845  	var x [9]byte
   846  	p := new([9]byte)
   847  	Escape(p)
   848  	b.ResetTimer()
   849  	for i := 0; i < b.N; i++ {
   850  		*p = x
   851  	}
   852  }
   853  
   854  func BenchmarkCopyFat10(b *testing.B) {
   855  	var x [10]byte
   856  	p := new([10]byte)
   857  	Escape(p)
   858  	b.ResetTimer()
   859  	for i := 0; i < b.N; i++ {
   860  		*p = x
   861  	}
   862  }
   863  
   864  func BenchmarkCopyFat11(b *testing.B) {
   865  	var x [11]byte
   866  	p := new([11]byte)
   867  	Escape(p)
   868  	b.ResetTimer()
   869  	for i := 0; i < b.N; i++ {
   870  		*p = x
   871  	}
   872  }
   873  
   874  func BenchmarkCopyFat12(b *testing.B) {
   875  	var x [12 / 4]uint32
   876  	p := new([12 / 4]uint32)
   877  	Escape(p)
   878  	b.ResetTimer()
   879  	for i := 0; i < b.N; i++ {
   880  		*p = x
   881  	}
   882  }
   883  
   884  func BenchmarkCopyFat13(b *testing.B) {
   885  	var x [13]byte
   886  	p := new([13]byte)
   887  	Escape(p)
   888  	b.ResetTimer()
   889  	for i := 0; i < b.N; i++ {
   890  		*p = x
   891  	}
   892  }
   893  
   894  func BenchmarkCopyFat14(b *testing.B) {
   895  	var x [14]byte
   896  	p := new([14]byte)
   897  	Escape(p)
   898  	b.ResetTimer()
   899  	for i := 0; i < b.N; i++ {
   900  		*p = x
   901  	}
   902  }
   903  
   904  func BenchmarkCopyFat15(b *testing.B) {
   905  	var x [15]byte
   906  	p := new([15]byte)
   907  	Escape(p)
   908  	b.ResetTimer()
   909  	for i := 0; i < b.N; i++ {
   910  		*p = x
   911  	}
   912  }
   913  
   914  func BenchmarkCopyFat16(b *testing.B) {
   915  	var x [16 / 4]uint32
   916  	p := new([16 / 4]uint32)
   917  	Escape(p)
   918  	b.ResetTimer()
   919  	for i := 0; i < b.N; i++ {
   920  		*p = x
   921  	}
   922  }
   923  
   924  func BenchmarkCopyFat18(b *testing.B) {
   925  	var x [18]byte
   926  	p := new([18]byte)
   927  	Escape(p)
   928  	b.ResetTimer()
   929  	for i := 0; i < b.N; i++ {
   930  		*p = x
   931  	}
   932  }
   933  
   934  func BenchmarkCopyFat20(b *testing.B) {
   935  	var x [20 / 4]uint32
   936  	p := new([20 / 4]uint32)
   937  	Escape(p)
   938  	b.ResetTimer()
   939  	for i := 0; i < b.N; i++ {
   940  		*p = x
   941  	}
   942  }
   943  
   944  func BenchmarkCopyFat24(b *testing.B) {
   945  	var x [24 / 4]uint32
   946  	p := new([24 / 4]uint32)
   947  	Escape(p)
   948  	b.ResetTimer()
   949  	for i := 0; i < b.N; i++ {
   950  		*p = x
   951  	}
   952  }
   953  
   954  func BenchmarkCopyFat32(b *testing.B) {
   955  	var x [32 / 4]uint32
   956  	p := new([32 / 4]uint32)
   957  	Escape(p)
   958  	b.ResetTimer()
   959  	for i := 0; i < b.N; i++ {
   960  		*p = x
   961  	}
   962  }
   963  
   964  func BenchmarkCopyFat64(b *testing.B) {
   965  	var x [64 / 4]uint32
   966  	p := new([64 / 4]uint32)
   967  	Escape(p)
   968  	b.ResetTimer()
   969  	for i := 0; i < b.N; i++ {
   970  		*p = x
   971  	}
   972  }
   973  
   974  func BenchmarkCopyFat72(b *testing.B) {
   975  	var x [72 / 4]uint32
   976  	p := new([72 / 4]uint32)
   977  	Escape(p)
   978  	b.ResetTimer()
   979  	for i := 0; i < b.N; i++ {
   980  		*p = x
   981  	}
   982  }
   983  
   984  func BenchmarkCopyFat128(b *testing.B) {
   985  	var x [128 / 4]uint32
   986  	p := new([128 / 4]uint32)
   987  	Escape(p)
   988  	b.ResetTimer()
   989  	for i := 0; i < b.N; i++ {
   990  		*p = x
   991  	}
   992  }
   993  
   994  func BenchmarkCopyFat256(b *testing.B) {
   995  	var x [256 / 4]uint32
   996  	p := new([256 / 4]uint32)
   997  	Escape(p)
   998  	b.ResetTimer()
   999  	for i := 0; i < b.N; i++ {
  1000  		*p = x
  1001  	}
  1002  }
  1003  
  1004  func BenchmarkCopyFat512(b *testing.B) {
  1005  	var x [512 / 4]uint32
  1006  	p := new([512 / 4]uint32)
  1007  	Escape(p)
  1008  	b.ResetTimer()
  1009  	for i := 0; i < b.N; i++ {
  1010  		*p = x
  1011  	}
  1012  }
  1013  
  1014  func BenchmarkCopyFat520(b *testing.B) {
  1015  	var x [520 / 4]uint32
  1016  	p := new([520 / 4]uint32)
  1017  	Escape(p)
  1018  	b.ResetTimer()
  1019  	for i := 0; i < b.N; i++ {
  1020  		*p = x
  1021  	}
  1022  }
  1023  
  1024  func BenchmarkCopyFat1024(b *testing.B) {
  1025  	var x [1024 / 4]uint32
  1026  	p := new([1024 / 4]uint32)
  1027  	Escape(p)
  1028  	b.ResetTimer()
  1029  	for i := 0; i < b.N; i++ {
  1030  		*p = x
  1031  	}
  1032  }
  1033  
  1034  func BenchmarkCopyFat1032(b *testing.B) {
  1035  	var x [1032 / 4]uint32
  1036  	p := new([1032 / 4]uint32)
  1037  	Escape(p)
  1038  	b.ResetTimer()
  1039  	for i := 0; i < b.N; i++ {
  1040  		*p = x
  1041  	}
  1042  }
  1043  
  1044  func BenchmarkCopyFat1040(b *testing.B) {
  1045  	var x [1040 / 4]uint32
  1046  	p := new([1040 / 4]uint32)
  1047  	Escape(p)
  1048  	b.ResetTimer()
  1049  	for i := 0; i < b.N; i++ {
  1050  		*p = x
  1051  	}
  1052  }
  1053  
  1054  // BenchmarkIssue18740 ensures that memmove uses 4 and 8 byte load/store to move 4 and 8 bytes.
  1055  // It used to do 2 2-byte load/stores, which leads to a pipeline stall
  1056  // when we try to read the result with one 4-byte load.
  1057  func BenchmarkIssue18740(b *testing.B) {
  1058  	benchmarks := []struct {
  1059  		name  string
  1060  		nbyte int
  1061  		f     func([]byte) uint64
  1062  	}{
  1063  		{"2byte", 2, func(buf []byte) uint64 { return uint64(binary.LittleEndian.Uint16(buf)) }},
  1064  		{"4byte", 4, func(buf []byte) uint64 { return uint64(binary.LittleEndian.Uint32(buf)) }},
  1065  		{"8byte", 8, func(buf []byte) uint64 { return binary.LittleEndian.Uint64(buf) }},
  1066  	}
  1067  
  1068  	var g [4096]byte
  1069  	for _, bm := range benchmarks {
  1070  		buf := make([]byte, bm.nbyte)
  1071  		b.Run(bm.name, func(b *testing.B) {
  1072  			for j := 0; j < b.N; j++ {
  1073  				for i := 0; i < 4096; i += bm.nbyte {
  1074  					copy(buf[:], g[i:])
  1075  					sink += bm.f(buf[:])
  1076  				}
  1077  			}
  1078  		})
  1079  	}
  1080  }
  1081  
  1082  var memclrSink []int8
  1083  
  1084  func BenchmarkMemclrKnownSize1(b *testing.B) {
  1085  	var x [1]int8
  1086  
  1087  	b.SetBytes(1)
  1088  	for i := 0; i < b.N; i++ {
  1089  		for a := range x {
  1090  			x[a] = 0
  1091  		}
  1092  	}
  1093  
  1094  	memclrSink = x[:]
  1095  }
  1096  func BenchmarkMemclrKnownSize2(b *testing.B) {
  1097  	var x [2]int8
  1098  
  1099  	b.SetBytes(2)
  1100  	for i := 0; i < b.N; i++ {
  1101  		for a := range x {
  1102  			x[a] = 0
  1103  		}
  1104  	}
  1105  
  1106  	memclrSink = x[:]
  1107  }
  1108  func BenchmarkMemclrKnownSize4(b *testing.B) {
  1109  	var x [4]int8
  1110  
  1111  	b.SetBytes(4)
  1112  	for i := 0; i < b.N; i++ {
  1113  		for a := range x {
  1114  			x[a] = 0
  1115  		}
  1116  	}
  1117  
  1118  	memclrSink = x[:]
  1119  }
  1120  func BenchmarkMemclrKnownSize8(b *testing.B) {
  1121  	var x [8]int8
  1122  
  1123  	b.SetBytes(8)
  1124  	for i := 0; i < b.N; i++ {
  1125  		for a := range x {
  1126  			x[a] = 0
  1127  		}
  1128  	}
  1129  
  1130  	memclrSink = x[:]
  1131  }
  1132  func BenchmarkMemclrKnownSize16(b *testing.B) {
  1133  	var x [16]int8
  1134  
  1135  	b.SetBytes(16)
  1136  	for i := 0; i < b.N; i++ {
  1137  		for a := range x {
  1138  			x[a] = 0
  1139  		}
  1140  	}
  1141  
  1142  	memclrSink = x[:]
  1143  }
  1144  func BenchmarkMemclrKnownSize32(b *testing.B) {
  1145  	var x [32]int8
  1146  
  1147  	b.SetBytes(32)
  1148  	for i := 0; i < b.N; i++ {
  1149  		for a := range x {
  1150  			x[a] = 0
  1151  		}
  1152  	}
  1153  
  1154  	memclrSink = x[:]
  1155  }
  1156  func BenchmarkMemclrKnownSize64(b *testing.B) {
  1157  	var x [64]int8
  1158  
  1159  	b.SetBytes(64)
  1160  	for i := 0; i < b.N; i++ {
  1161  		for a := range x {
  1162  			x[a] = 0
  1163  		}
  1164  	}
  1165  
  1166  	memclrSink = x[:]
  1167  }
  1168  func BenchmarkMemclrKnownSize112(b *testing.B) {
  1169  	var x [112]int8
  1170  
  1171  	b.SetBytes(112)
  1172  	for i := 0; i < b.N; i++ {
  1173  		for a := range x {
  1174  			x[a] = 0
  1175  		}
  1176  	}
  1177  
  1178  	memclrSink = x[:]
  1179  }
  1180  
  1181  func BenchmarkMemclrKnownSize128(b *testing.B) {
  1182  	var x [128]int8
  1183  
  1184  	b.SetBytes(128)
  1185  	for i := 0; i < b.N; i++ {
  1186  		for a := range x {
  1187  			x[a] = 0
  1188  		}
  1189  	}
  1190  
  1191  	memclrSink = x[:]
  1192  }
  1193  
  1194  func BenchmarkMemclrKnownSize192(b *testing.B) {
  1195  	var x [192]int8
  1196  
  1197  	b.SetBytes(192)
  1198  	for i := 0; i < b.N; i++ {
  1199  		for a := range x {
  1200  			x[a] = 0
  1201  		}
  1202  	}
  1203  
  1204  	memclrSink = x[:]
  1205  }
  1206  
  1207  func BenchmarkMemclrKnownSize248(b *testing.B) {
  1208  	var x [248]int8
  1209  
  1210  	b.SetBytes(248)
  1211  	for i := 0; i < b.N; i++ {
  1212  		for a := range x {
  1213  			x[a] = 0
  1214  		}
  1215  	}
  1216  
  1217  	memclrSink = x[:]
  1218  }
  1219  
  1220  func BenchmarkMemclrKnownSize256(b *testing.B) {
  1221  	var x [256]int8
  1222  
  1223  	b.SetBytes(256)
  1224  	for i := 0; i < b.N; i++ {
  1225  		for a := range x {
  1226  			x[a] = 0
  1227  		}
  1228  	}
  1229  
  1230  	memclrSink = x[:]
  1231  }
  1232  func BenchmarkMemclrKnownSize512(b *testing.B) {
  1233  	var x [512]int8
  1234  
  1235  	b.SetBytes(512)
  1236  	for i := 0; i < b.N; i++ {
  1237  		for a := range x {
  1238  			x[a] = 0
  1239  		}
  1240  	}
  1241  
  1242  	memclrSink = x[:]
  1243  }
  1244  func BenchmarkMemclrKnownSize1024(b *testing.B) {
  1245  	var x [1024]int8
  1246  
  1247  	b.SetBytes(1024)
  1248  	for i := 0; i < b.N; i++ {
  1249  		for a := range x {
  1250  			x[a] = 0
  1251  		}
  1252  	}
  1253  
  1254  	memclrSink = x[:]
  1255  }
  1256  func BenchmarkMemclrKnownSize4096(b *testing.B) {
  1257  	var x [4096]int8
  1258  
  1259  	b.SetBytes(4096)
  1260  	for i := 0; i < b.N; i++ {
  1261  		for a := range x {
  1262  			x[a] = 0
  1263  		}
  1264  	}
  1265  
  1266  	memclrSink = x[:]
  1267  }
  1268  func BenchmarkMemclrKnownSize512KiB(b *testing.B) {
  1269  	var x [524288]int8
  1270  
  1271  	b.SetBytes(524288)
  1272  	for i := 0; i < b.N; i++ {
  1273  		for a := range x {
  1274  			x[a] = 0
  1275  		}
  1276  	}
  1277  
  1278  	memclrSink = x[:]
  1279  }
  1280  
  1281  func BenchmarkMemmoveKnownSize112(b *testing.B) {
  1282  	type T struct {
  1283  		x [112]int8
  1284  	}
  1285  	p := &T{}
  1286  	q := &T{}
  1287  
  1288  	b.SetBytes(int64(unsafe.Sizeof(T{})))
  1289  	for i := 0; i < b.N; i++ {
  1290  		*p = *q
  1291  	}
  1292  
  1293  	memclrSink = p.x[:]
  1294  }
  1295  func BenchmarkMemmoveKnownSize128(b *testing.B) {
  1296  	type T struct {
  1297  		x [128]int8
  1298  	}
  1299  	p := &T{}
  1300  	q := &T{}
  1301  
  1302  	b.SetBytes(int64(unsafe.Sizeof(T{})))
  1303  	for i := 0; i < b.N; i++ {
  1304  		*p = *q
  1305  	}
  1306  
  1307  	memclrSink = p.x[:]
  1308  }
  1309  func BenchmarkMemmoveKnownSize192(b *testing.B) {
  1310  	type T struct {
  1311  		x [192]int8
  1312  	}
  1313  	p := &T{}
  1314  	q := &T{}
  1315  
  1316  	b.SetBytes(int64(unsafe.Sizeof(T{})))
  1317  	for i := 0; i < b.N; i++ {
  1318  		*p = *q
  1319  	}
  1320  
  1321  	memclrSink = p.x[:]
  1322  }
  1323  func BenchmarkMemmoveKnownSize248(b *testing.B) {
  1324  	type T struct {
  1325  		x [248]int8
  1326  	}
  1327  	p := &T{}
  1328  	q := &T{}
  1329  
  1330  	b.SetBytes(int64(unsafe.Sizeof(T{})))
  1331  	for i := 0; i < b.N; i++ {
  1332  		*p = *q
  1333  	}
  1334  
  1335  	memclrSink = p.x[:]
  1336  }
  1337  func BenchmarkMemmoveKnownSize256(b *testing.B) {
  1338  	type T struct {
  1339  		x [256]int8
  1340  	}
  1341  	p := &T{}
  1342  	q := &T{}
  1343  
  1344  	b.SetBytes(int64(unsafe.Sizeof(T{})))
  1345  	for i := 0; i < b.N; i++ {
  1346  		*p = *q
  1347  	}
  1348  
  1349  	memclrSink = p.x[:]
  1350  }
  1351  func BenchmarkMemmoveKnownSize512(b *testing.B) {
  1352  	type T struct {
  1353  		x [512]int8
  1354  	}
  1355  	p := &T{}
  1356  	q := &T{}
  1357  
  1358  	b.SetBytes(int64(unsafe.Sizeof(T{})))
  1359  	for i := 0; i < b.N; i++ {
  1360  		*p = *q
  1361  	}
  1362  
  1363  	memclrSink = p.x[:]
  1364  }
  1365  func BenchmarkMemmoveKnownSize1024(b *testing.B) {
  1366  	type T struct {
  1367  		x [1024]int8
  1368  	}
  1369  	p := &T{}
  1370  	q := &T{}
  1371  
  1372  	b.SetBytes(int64(unsafe.Sizeof(T{})))
  1373  	for i := 0; i < b.N; i++ {
  1374  		*p = *q
  1375  	}
  1376  
  1377  	memclrSink = p.x[:]
  1378  }
  1379  

View as plain text