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 BenchmarkClearFat7(b *testing.B) {
   524  	p := new([7]byte)
   525  	Escape(p)
   526  	b.ResetTimer()
   527  	for i := 0; i < b.N; i++ {
   528  		*p = [7]byte{}
   529  	}
   530  }
   531  
   532  func BenchmarkClearFat8(b *testing.B) {
   533  	p := new([8 / 4]uint32)
   534  	Escape(p)
   535  	b.ResetTimer()
   536  	for i := 0; i < b.N; i++ {
   537  		*p = [8 / 4]uint32{}
   538  	}
   539  }
   540  
   541  func BenchmarkClearFat11(b *testing.B) {
   542  	p := new([11]byte)
   543  	Escape(p)
   544  	b.ResetTimer()
   545  	for i := 0; i < b.N; i++ {
   546  		*p = [11]byte{}
   547  	}
   548  }
   549  
   550  func BenchmarkClearFat12(b *testing.B) {
   551  	p := new([12 / 4]uint32)
   552  	Escape(p)
   553  	b.ResetTimer()
   554  	for i := 0; i < b.N; i++ {
   555  		*p = [12 / 4]uint32{}
   556  	}
   557  }
   558  
   559  func BenchmarkClearFat13(b *testing.B) {
   560  	p := new([13]byte)
   561  	Escape(p)
   562  	b.ResetTimer()
   563  	for i := 0; i < b.N; i++ {
   564  		*p = [13]byte{}
   565  	}
   566  }
   567  
   568  func BenchmarkClearFat14(b *testing.B) {
   569  	p := new([14]byte)
   570  	Escape(p)
   571  	b.ResetTimer()
   572  	for i := 0; i < b.N; i++ {
   573  		*p = [14]byte{}
   574  	}
   575  }
   576  
   577  func BenchmarkClearFat15(b *testing.B) {
   578  	p := new([15]byte)
   579  	Escape(p)
   580  	b.ResetTimer()
   581  	for i := 0; i < b.N; i++ {
   582  		*p = [15]byte{}
   583  	}
   584  }
   585  
   586  func BenchmarkClearFat16(b *testing.B) {
   587  	p := new([16 / 4]uint32)
   588  	Escape(p)
   589  	b.ResetTimer()
   590  	for i := 0; i < b.N; i++ {
   591  		*p = [16 / 4]uint32{}
   592  	}
   593  }
   594  
   595  func BenchmarkClearFat24(b *testing.B) {
   596  	p := new([24 / 4]uint32)
   597  	Escape(p)
   598  	b.ResetTimer()
   599  	for i := 0; i < b.N; i++ {
   600  		*p = [24 / 4]uint32{}
   601  	}
   602  }
   603  
   604  func BenchmarkClearFat32(b *testing.B) {
   605  	p := new([32 / 4]uint32)
   606  	Escape(p)
   607  	b.ResetTimer()
   608  	for i := 0; i < b.N; i++ {
   609  		*p = [32 / 4]uint32{}
   610  	}
   611  }
   612  
   613  func BenchmarkClearFat40(b *testing.B) {
   614  	p := new([40 / 4]uint32)
   615  	Escape(p)
   616  	b.ResetTimer()
   617  	for i := 0; i < b.N; i++ {
   618  		*p = [40 / 4]uint32{}
   619  	}
   620  }
   621  
   622  func BenchmarkClearFat48(b *testing.B) {
   623  	p := new([48 / 4]uint32)
   624  	Escape(p)
   625  	b.ResetTimer()
   626  	for i := 0; i < b.N; i++ {
   627  		*p = [48 / 4]uint32{}
   628  	}
   629  }
   630  
   631  func BenchmarkClearFat56(b *testing.B) {
   632  	p := new([56 / 4]uint32)
   633  	Escape(p)
   634  	b.ResetTimer()
   635  	for i := 0; i < b.N; i++ {
   636  		*p = [56 / 4]uint32{}
   637  	}
   638  }
   639  
   640  func BenchmarkClearFat64(b *testing.B) {
   641  	p := new([64 / 4]uint32)
   642  	Escape(p)
   643  	b.ResetTimer()
   644  	for i := 0; i < b.N; i++ {
   645  		*p = [64 / 4]uint32{}
   646  	}
   647  }
   648  
   649  func BenchmarkClearFat72(b *testing.B) {
   650  	p := new([72 / 4]uint32)
   651  	Escape(p)
   652  	b.ResetTimer()
   653  	for i := 0; i < b.N; i++ {
   654  		*p = [72 / 4]uint32{}
   655  	}
   656  }
   657  
   658  func BenchmarkClearFat128(b *testing.B) {
   659  	p := new([128 / 4]uint32)
   660  	Escape(p)
   661  	b.ResetTimer()
   662  	for i := 0; i < b.N; i++ {
   663  		*p = [128 / 4]uint32{}
   664  	}
   665  }
   666  
   667  func BenchmarkClearFat256(b *testing.B) {
   668  	p := new([256 / 4]uint32)
   669  	Escape(p)
   670  	b.ResetTimer()
   671  	for i := 0; i < b.N; i++ {
   672  		*p = [256 / 4]uint32{}
   673  	}
   674  }
   675  
   676  func BenchmarkClearFat512(b *testing.B) {
   677  	p := new([512 / 4]uint32)
   678  	Escape(p)
   679  	b.ResetTimer()
   680  	for i := 0; i < b.N; i++ {
   681  		*p = [512 / 4]uint32{}
   682  	}
   683  }
   684  
   685  func BenchmarkClearFat1024(b *testing.B) {
   686  	p := new([1024 / 4]uint32)
   687  	Escape(p)
   688  	b.ResetTimer()
   689  	for i := 0; i < b.N; i++ {
   690  		*p = [1024 / 4]uint32{}
   691  	}
   692  }
   693  
   694  func BenchmarkClearFat1032(b *testing.B) {
   695  	p := new([1032 / 4]uint32)
   696  	Escape(p)
   697  	b.ResetTimer()
   698  	for i := 0; i < b.N; i++ {
   699  		*p = [1032 / 4]uint32{}
   700  	}
   701  }
   702  
   703  func BenchmarkClearFat1040(b *testing.B) {
   704  	p := new([1040 / 4]uint32)
   705  	Escape(p)
   706  	b.ResetTimer()
   707  	for i := 0; i < b.N; i++ {
   708  		*p = [1040 / 4]uint32{}
   709  	}
   710  }
   711  
   712  func BenchmarkCopyFat7(b *testing.B) {
   713  	var x [7]byte
   714  	p := new([7]byte)
   715  	Escape(p)
   716  	b.ResetTimer()
   717  	for i := 0; i < b.N; i++ {
   718  		*p = x
   719  	}
   720  }
   721  
   722  func BenchmarkCopyFat8(b *testing.B) {
   723  	var x [8 / 4]uint32
   724  	p := new([8 / 4]uint32)
   725  	Escape(p)
   726  	b.ResetTimer()
   727  	for i := 0; i < b.N; i++ {
   728  		*p = x
   729  	}
   730  }
   731  
   732  func BenchmarkCopyFat11(b *testing.B) {
   733  	var x [11]byte
   734  	p := new([11]byte)
   735  	Escape(p)
   736  	b.ResetTimer()
   737  	for i := 0; i < b.N; i++ {
   738  		*p = x
   739  	}
   740  }
   741  
   742  func BenchmarkCopyFat12(b *testing.B) {
   743  	var x [12 / 4]uint32
   744  	p := new([12 / 4]uint32)
   745  	Escape(p)
   746  	b.ResetTimer()
   747  	for i := 0; i < b.N; i++ {
   748  		*p = x
   749  	}
   750  }
   751  
   752  func BenchmarkCopyFat13(b *testing.B) {
   753  	var x [13]byte
   754  	p := new([13]byte)
   755  	Escape(p)
   756  	b.ResetTimer()
   757  	for i := 0; i < b.N; i++ {
   758  		*p = x
   759  	}
   760  }
   761  
   762  func BenchmarkCopyFat14(b *testing.B) {
   763  	var x [14]byte
   764  	p := new([14]byte)
   765  	Escape(p)
   766  	b.ResetTimer()
   767  	for i := 0; i < b.N; i++ {
   768  		*p = x
   769  	}
   770  }
   771  
   772  func BenchmarkCopyFat15(b *testing.B) {
   773  	var x [15]byte
   774  	p := new([15]byte)
   775  	Escape(p)
   776  	b.ResetTimer()
   777  	for i := 0; i < b.N; i++ {
   778  		*p = x
   779  	}
   780  }
   781  
   782  func BenchmarkCopyFat16(b *testing.B) {
   783  	var x [16 / 4]uint32
   784  	p := new([16 / 4]uint32)
   785  	Escape(p)
   786  	b.ResetTimer()
   787  	for i := 0; i < b.N; i++ {
   788  		*p = x
   789  	}
   790  }
   791  
   792  func BenchmarkCopyFat24(b *testing.B) {
   793  	var x [24 / 4]uint32
   794  	p := new([24 / 4]uint32)
   795  	Escape(p)
   796  	b.ResetTimer()
   797  	for i := 0; i < b.N; i++ {
   798  		*p = x
   799  	}
   800  }
   801  
   802  func BenchmarkCopyFat32(b *testing.B) {
   803  	var x [32 / 4]uint32
   804  	p := new([32 / 4]uint32)
   805  	Escape(p)
   806  	b.ResetTimer()
   807  	for i := 0; i < b.N; i++ {
   808  		*p = x
   809  	}
   810  }
   811  
   812  func BenchmarkCopyFat64(b *testing.B) {
   813  	var x [64 / 4]uint32
   814  	p := new([64 / 4]uint32)
   815  	Escape(p)
   816  	b.ResetTimer()
   817  	for i := 0; i < b.N; i++ {
   818  		*p = x
   819  	}
   820  }
   821  
   822  func BenchmarkCopyFat72(b *testing.B) {
   823  	var x [72 / 4]uint32
   824  	p := new([72 / 4]uint32)
   825  	Escape(p)
   826  	b.ResetTimer()
   827  	for i := 0; i < b.N; i++ {
   828  		*p = x
   829  	}
   830  }
   831  
   832  func BenchmarkCopyFat128(b *testing.B) {
   833  	var x [128 / 4]uint32
   834  	p := new([128 / 4]uint32)
   835  	Escape(p)
   836  	b.ResetTimer()
   837  	for i := 0; i < b.N; i++ {
   838  		*p = x
   839  	}
   840  }
   841  
   842  func BenchmarkCopyFat256(b *testing.B) {
   843  	var x [256 / 4]uint32
   844  	p := new([256 / 4]uint32)
   845  	Escape(p)
   846  	b.ResetTimer()
   847  	for i := 0; i < b.N; i++ {
   848  		*p = x
   849  	}
   850  }
   851  
   852  func BenchmarkCopyFat512(b *testing.B) {
   853  	var x [512 / 4]uint32
   854  	p := new([512 / 4]uint32)
   855  	Escape(p)
   856  	b.ResetTimer()
   857  	for i := 0; i < b.N; i++ {
   858  		*p = x
   859  	}
   860  }
   861  
   862  func BenchmarkCopyFat520(b *testing.B) {
   863  	var x [520 / 4]uint32
   864  	p := new([520 / 4]uint32)
   865  	Escape(p)
   866  	b.ResetTimer()
   867  	for i := 0; i < b.N; i++ {
   868  		*p = x
   869  	}
   870  }
   871  
   872  func BenchmarkCopyFat1024(b *testing.B) {
   873  	var x [1024 / 4]uint32
   874  	p := new([1024 / 4]uint32)
   875  	Escape(p)
   876  	b.ResetTimer()
   877  	for i := 0; i < b.N; i++ {
   878  		*p = x
   879  	}
   880  }
   881  
   882  func BenchmarkCopyFat1032(b *testing.B) {
   883  	var x [1032 / 4]uint32
   884  	p := new([1032 / 4]uint32)
   885  	Escape(p)
   886  	b.ResetTimer()
   887  	for i := 0; i < b.N; i++ {
   888  		*p = x
   889  	}
   890  }
   891  
   892  func BenchmarkCopyFat1040(b *testing.B) {
   893  	var x [1040 / 4]uint32
   894  	p := new([1040 / 4]uint32)
   895  	Escape(p)
   896  	b.ResetTimer()
   897  	for i := 0; i < b.N; i++ {
   898  		*p = x
   899  	}
   900  }
   901  
   902  // BenchmarkIssue18740 ensures that memmove uses 4 and 8 byte load/store to move 4 and 8 bytes.
   903  // It used to do 2 2-byte load/stores, which leads to a pipeline stall
   904  // when we try to read the result with one 4-byte load.
   905  func BenchmarkIssue18740(b *testing.B) {
   906  	benchmarks := []struct {
   907  		name  string
   908  		nbyte int
   909  		f     func([]byte) uint64
   910  	}{
   911  		{"2byte", 2, func(buf []byte) uint64 { return uint64(binary.LittleEndian.Uint16(buf)) }},
   912  		{"4byte", 4, func(buf []byte) uint64 { return uint64(binary.LittleEndian.Uint32(buf)) }},
   913  		{"8byte", 8, func(buf []byte) uint64 { return binary.LittleEndian.Uint64(buf) }},
   914  	}
   915  
   916  	var g [4096]byte
   917  	for _, bm := range benchmarks {
   918  		buf := make([]byte, bm.nbyte)
   919  		b.Run(bm.name, func(b *testing.B) {
   920  			for j := 0; j < b.N; j++ {
   921  				for i := 0; i < 4096; i += bm.nbyte {
   922  					copy(buf[:], g[i:])
   923  					sink += bm.f(buf[:])
   924  				}
   925  			}
   926  		})
   927  	}
   928  }
   929  
   930  var memclrSink []int8
   931  
   932  func BenchmarkMemclrKnownSize1(b *testing.B) {
   933  	var x [1]int8
   934  
   935  	b.SetBytes(1)
   936  	for i := 0; i < b.N; i++ {
   937  		for a := range x {
   938  			x[a] = 0
   939  		}
   940  	}
   941  
   942  	memclrSink = x[:]
   943  }
   944  func BenchmarkMemclrKnownSize2(b *testing.B) {
   945  	var x [2]int8
   946  
   947  	b.SetBytes(2)
   948  	for i := 0; i < b.N; i++ {
   949  		for a := range x {
   950  			x[a] = 0
   951  		}
   952  	}
   953  
   954  	memclrSink = x[:]
   955  }
   956  func BenchmarkMemclrKnownSize4(b *testing.B) {
   957  	var x [4]int8
   958  
   959  	b.SetBytes(4)
   960  	for i := 0; i < b.N; i++ {
   961  		for a := range x {
   962  			x[a] = 0
   963  		}
   964  	}
   965  
   966  	memclrSink = x[:]
   967  }
   968  func BenchmarkMemclrKnownSize8(b *testing.B) {
   969  	var x [8]int8
   970  
   971  	b.SetBytes(8)
   972  	for i := 0; i < b.N; i++ {
   973  		for a := range x {
   974  			x[a] = 0
   975  		}
   976  	}
   977  
   978  	memclrSink = x[:]
   979  }
   980  func BenchmarkMemclrKnownSize16(b *testing.B) {
   981  	var x [16]int8
   982  
   983  	b.SetBytes(16)
   984  	for i := 0; i < b.N; i++ {
   985  		for a := range x {
   986  			x[a] = 0
   987  		}
   988  	}
   989  
   990  	memclrSink = x[:]
   991  }
   992  func BenchmarkMemclrKnownSize32(b *testing.B) {
   993  	var x [32]int8
   994  
   995  	b.SetBytes(32)
   996  	for i := 0; i < b.N; i++ {
   997  		for a := range x {
   998  			x[a] = 0
   999  		}
  1000  	}
  1001  
  1002  	memclrSink = x[:]
  1003  }
  1004  func BenchmarkMemclrKnownSize64(b *testing.B) {
  1005  	var x [64]int8
  1006  
  1007  	b.SetBytes(64)
  1008  	for i := 0; i < b.N; i++ {
  1009  		for a := range x {
  1010  			x[a] = 0
  1011  		}
  1012  	}
  1013  
  1014  	memclrSink = x[:]
  1015  }
  1016  func BenchmarkMemclrKnownSize112(b *testing.B) {
  1017  	var x [112]int8
  1018  
  1019  	b.SetBytes(112)
  1020  	for i := 0; i < b.N; i++ {
  1021  		for a := range x {
  1022  			x[a] = 0
  1023  		}
  1024  	}
  1025  
  1026  	memclrSink = x[:]
  1027  }
  1028  
  1029  func BenchmarkMemclrKnownSize128(b *testing.B) {
  1030  	var x [128]int8
  1031  
  1032  	b.SetBytes(128)
  1033  	for i := 0; i < b.N; i++ {
  1034  		for a := range x {
  1035  			x[a] = 0
  1036  		}
  1037  	}
  1038  
  1039  	memclrSink = x[:]
  1040  }
  1041  
  1042  func BenchmarkMemclrKnownSize192(b *testing.B) {
  1043  	var x [192]int8
  1044  
  1045  	b.SetBytes(192)
  1046  	for i := 0; i < b.N; i++ {
  1047  		for a := range x {
  1048  			x[a] = 0
  1049  		}
  1050  	}
  1051  
  1052  	memclrSink = x[:]
  1053  }
  1054  
  1055  func BenchmarkMemclrKnownSize248(b *testing.B) {
  1056  	var x [248]int8
  1057  
  1058  	b.SetBytes(248)
  1059  	for i := 0; i < b.N; i++ {
  1060  		for a := range x {
  1061  			x[a] = 0
  1062  		}
  1063  	}
  1064  
  1065  	memclrSink = x[:]
  1066  }
  1067  
  1068  func BenchmarkMemclrKnownSize256(b *testing.B) {
  1069  	var x [256]int8
  1070  
  1071  	b.SetBytes(256)
  1072  	for i := 0; i < b.N; i++ {
  1073  		for a := range x {
  1074  			x[a] = 0
  1075  		}
  1076  	}
  1077  
  1078  	memclrSink = x[:]
  1079  }
  1080  func BenchmarkMemclrKnownSize512(b *testing.B) {
  1081  	var x [512]int8
  1082  
  1083  	b.SetBytes(512)
  1084  	for i := 0; i < b.N; i++ {
  1085  		for a := range x {
  1086  			x[a] = 0
  1087  		}
  1088  	}
  1089  
  1090  	memclrSink = x[:]
  1091  }
  1092  func BenchmarkMemclrKnownSize1024(b *testing.B) {
  1093  	var x [1024]int8
  1094  
  1095  	b.SetBytes(1024)
  1096  	for i := 0; i < b.N; i++ {
  1097  		for a := range x {
  1098  			x[a] = 0
  1099  		}
  1100  	}
  1101  
  1102  	memclrSink = x[:]
  1103  }
  1104  func BenchmarkMemclrKnownSize4096(b *testing.B) {
  1105  	var x [4096]int8
  1106  
  1107  	b.SetBytes(4096)
  1108  	for i := 0; i < b.N; i++ {
  1109  		for a := range x {
  1110  			x[a] = 0
  1111  		}
  1112  	}
  1113  
  1114  	memclrSink = x[:]
  1115  }
  1116  func BenchmarkMemclrKnownSize512KiB(b *testing.B) {
  1117  	var x [524288]int8
  1118  
  1119  	b.SetBytes(524288)
  1120  	for i := 0; i < b.N; i++ {
  1121  		for a := range x {
  1122  			x[a] = 0
  1123  		}
  1124  	}
  1125  
  1126  	memclrSink = x[:]
  1127  }
  1128  
  1129  func BenchmarkMemmoveKnownSize112(b *testing.B) {
  1130  	type T struct {
  1131  		x [112]int8
  1132  	}
  1133  	p := &T{}
  1134  	q := &T{}
  1135  
  1136  	b.SetBytes(int64(unsafe.Sizeof(T{})))
  1137  	for i := 0; i < b.N; i++ {
  1138  		*p = *q
  1139  	}
  1140  
  1141  	memclrSink = p.x[:]
  1142  }
  1143  func BenchmarkMemmoveKnownSize128(b *testing.B) {
  1144  	type T struct {
  1145  		x [128]int8
  1146  	}
  1147  	p := &T{}
  1148  	q := &T{}
  1149  
  1150  	b.SetBytes(int64(unsafe.Sizeof(T{})))
  1151  	for i := 0; i < b.N; i++ {
  1152  		*p = *q
  1153  	}
  1154  
  1155  	memclrSink = p.x[:]
  1156  }
  1157  func BenchmarkMemmoveKnownSize192(b *testing.B) {
  1158  	type T struct {
  1159  		x [192]int8
  1160  	}
  1161  	p := &T{}
  1162  	q := &T{}
  1163  
  1164  	b.SetBytes(int64(unsafe.Sizeof(T{})))
  1165  	for i := 0; i < b.N; i++ {
  1166  		*p = *q
  1167  	}
  1168  
  1169  	memclrSink = p.x[:]
  1170  }
  1171  func BenchmarkMemmoveKnownSize248(b *testing.B) {
  1172  	type T struct {
  1173  		x [248]int8
  1174  	}
  1175  	p := &T{}
  1176  	q := &T{}
  1177  
  1178  	b.SetBytes(int64(unsafe.Sizeof(T{})))
  1179  	for i := 0; i < b.N; i++ {
  1180  		*p = *q
  1181  	}
  1182  
  1183  	memclrSink = p.x[:]
  1184  }
  1185  func BenchmarkMemmoveKnownSize256(b *testing.B) {
  1186  	type T struct {
  1187  		x [256]int8
  1188  	}
  1189  	p := &T{}
  1190  	q := &T{}
  1191  
  1192  	b.SetBytes(int64(unsafe.Sizeof(T{})))
  1193  	for i := 0; i < b.N; i++ {
  1194  		*p = *q
  1195  	}
  1196  
  1197  	memclrSink = p.x[:]
  1198  }
  1199  func BenchmarkMemmoveKnownSize512(b *testing.B) {
  1200  	type T struct {
  1201  		x [512]int8
  1202  	}
  1203  	p := &T{}
  1204  	q := &T{}
  1205  
  1206  	b.SetBytes(int64(unsafe.Sizeof(T{})))
  1207  	for i := 0; i < b.N; i++ {
  1208  		*p = *q
  1209  	}
  1210  
  1211  	memclrSink = p.x[:]
  1212  }
  1213  func BenchmarkMemmoveKnownSize1024(b *testing.B) {
  1214  	type T struct {
  1215  		x [1024]int8
  1216  	}
  1217  	p := &T{}
  1218  	q := &T{}
  1219  
  1220  	b.SetBytes(int64(unsafe.Sizeof(T{})))
  1221  	for i := 0; i < b.N; i++ {
  1222  		*p = *q
  1223  	}
  1224  
  1225  	memclrSink = p.x[:]
  1226  }
  1227  

View as plain text