github.com/panjjo/go@v0.0.0-20161104043856-d62b31386338/src/runtime/memmove_test.go (about)

     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  	"fmt"
    10  	"internal/race"
    11  	. "runtime"
    12  	"testing"
    13  )
    14  
    15  func TestMemmove(t *testing.T) {
    16  	size := 256
    17  	if testing.Short() {
    18  		size = 128 + 16
    19  	}
    20  	src := make([]byte, size)
    21  	dst := make([]byte, size)
    22  	for i := 0; i < size; i++ {
    23  		src[i] = byte(128 + (i & 127))
    24  	}
    25  	for i := 0; i < size; i++ {
    26  		dst[i] = byte(i & 127)
    27  	}
    28  	for n := 0; n <= size; n++ {
    29  		for x := 0; x <= size-n; x++ { // offset in src
    30  			for y := 0; y <= size-n; y++ { // offset in dst
    31  				copy(dst[y:y+n], src[x:x+n])
    32  				for i := 0; i < y; i++ {
    33  					if dst[i] != byte(i&127) {
    34  						t.Fatalf("prefix dst[%d] = %d", i, dst[i])
    35  					}
    36  				}
    37  				for i := y; i < y+n; i++ {
    38  					if dst[i] != byte(128+((i-y+x)&127)) {
    39  						t.Fatalf("copied dst[%d] = %d", i, dst[i])
    40  					}
    41  					dst[i] = byte(i & 127) // reset dst
    42  				}
    43  				for i := y + n; i < size; i++ {
    44  					if dst[i] != byte(i&127) {
    45  						t.Fatalf("suffix dst[%d] = %d", i, dst[i])
    46  					}
    47  				}
    48  			}
    49  		}
    50  	}
    51  }
    52  
    53  func TestMemmoveAlias(t *testing.T) {
    54  	size := 256
    55  	if testing.Short() {
    56  		size = 128 + 16
    57  	}
    58  	buf := make([]byte, size)
    59  	for i := 0; i < size; i++ {
    60  		buf[i] = byte(i)
    61  	}
    62  	for n := 0; n <= size; n++ {
    63  		for x := 0; x <= size-n; x++ { // src offset
    64  			for y := 0; y <= size-n; y++ { // dst offset
    65  				copy(buf[y:y+n], buf[x:x+n])
    66  				for i := 0; i < y; i++ {
    67  					if buf[i] != byte(i) {
    68  						t.Fatalf("prefix buf[%d] = %d", i, buf[i])
    69  					}
    70  				}
    71  				for i := y; i < y+n; i++ {
    72  					if buf[i] != byte(i-y+x) {
    73  						t.Fatalf("copied buf[%d] = %d", i, buf[i])
    74  					}
    75  					buf[i] = byte(i) // reset buf
    76  				}
    77  				for i := y + n; i < size; i++ {
    78  					if buf[i] != byte(i) {
    79  						t.Fatalf("suffix buf[%d] = %d", i, buf[i])
    80  					}
    81  				}
    82  			}
    83  		}
    84  	}
    85  }
    86  
    87  func TestMemmoveLarge0x180000(t *testing.T) {
    88  	if race.Enabled {
    89  		t.Skip("skipping large memmove test under race detector")
    90  	}
    91  	testSize(t, 0x180000)
    92  }
    93  
    94  func TestMemmoveOverlapLarge0x120000(t *testing.T) {
    95  	if race.Enabled {
    96  		t.Skip("skipping large memmove test under race detector")
    97  	}
    98  	testOverlap(t, 0x120000)
    99  }
   100  
   101  func testSize(t *testing.T, size int) {
   102  	src := make([]byte, size)
   103  	dst := make([]byte, size)
   104  	_, _ = rand.Read(src)
   105  	_, _ = rand.Read(dst)
   106  
   107  	ref := make([]byte, size)
   108  	copyref(ref, dst)
   109  
   110  	for n := size - 50; n > 1; n >>= 1 {
   111  		for x := 0; x <= size-n; x = x*7 + 1 { // offset in src
   112  			for y := 0; y <= size-n; y = y*9 + 1 { // offset in dst
   113  				copy(dst[y:y+n], src[x:x+n])
   114  				copyref(ref[y:y+n], src[x:x+n])
   115  				p := cmpb(dst, ref)
   116  				if p >= 0 {
   117  					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])
   118  				}
   119  			}
   120  		}
   121  	}
   122  }
   123  
   124  func testOverlap(t *testing.T, size int) {
   125  	src := make([]byte, size)
   126  	test := make([]byte, size)
   127  	ref := make([]byte, size)
   128  	_, _ = rand.Read(src)
   129  
   130  	for n := size - 50; n > 1; n >>= 1 {
   131  		for x := 0; x <= size-n; x = x*7 + 1 { // offset in src
   132  			for y := 0; y <= size-n; y = y*9 + 1 { // offset in dst
   133  				// Reset input
   134  				copyref(test, src)
   135  				copyref(ref, src)
   136  				copy(test[y:y+n], test[x:x+n])
   137  				if y <= x {
   138  					copyref(ref[y:y+n], ref[x:x+n])
   139  				} else {
   140  					copybw(ref[y:y+n], ref[x:x+n])
   141  				}
   142  				p := cmpb(test, ref)
   143  				if p >= 0 {
   144  					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])
   145  				}
   146  			}
   147  		}
   148  	}
   149  
   150  }
   151  
   152  // Forward copy.
   153  func copyref(dst, src []byte) {
   154  	for i, v := range src {
   155  		dst[i] = v
   156  	}
   157  }
   158  
   159  // Backwards copy
   160  func copybw(dst, src []byte) {
   161  	if len(src) == 0 {
   162  		return
   163  	}
   164  	for i := len(src) - 1; i >= 0; i-- {
   165  		dst[i] = src[i]
   166  	}
   167  }
   168  
   169  // Returns offset of difference
   170  func matchLen(a, b []byte, max int) int {
   171  	a = a[:max]
   172  	b = b[:max]
   173  	for i, av := range a {
   174  		if b[i] != av {
   175  			return i
   176  		}
   177  	}
   178  	return max
   179  }
   180  
   181  func cmpb(a, b []byte) int {
   182  	l := matchLen(a, b, len(a))
   183  	if l == len(a) {
   184  		return -1
   185  	}
   186  	return l
   187  }
   188  
   189  func benchmarkSizes(b *testing.B, sizes []int, fn func(b *testing.B, n int)) {
   190  	for _, n := range sizes {
   191  		b.Run(fmt.Sprint(n), func(b *testing.B) {
   192  			b.SetBytes(int64(n))
   193  			fn(b, n)
   194  		})
   195  	}
   196  }
   197  
   198  var bufSizes = []int{
   199  	0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
   200  	32, 64, 128, 256, 512, 1024, 2048, 4096,
   201  }
   202  
   203  func BenchmarkMemmove(b *testing.B) {
   204  	benchmarkSizes(b, bufSizes, func(b *testing.B, n int) {
   205  		x := make([]byte, n)
   206  		y := make([]byte, n)
   207  		for i := 0; i < b.N; i++ {
   208  			copy(x, y)
   209  		}
   210  	})
   211  }
   212  
   213  func BenchmarkMemmoveUnalignedDst(b *testing.B) {
   214  	benchmarkSizes(b, bufSizes, func(b *testing.B, n int) {
   215  		x := make([]byte, n+1)
   216  		y := make([]byte, n)
   217  		for i := 0; i < b.N; i++ {
   218  			copy(x[1:], y)
   219  		}
   220  	})
   221  }
   222  
   223  func BenchmarkMemmoveUnalignedSrc(b *testing.B) {
   224  	benchmarkSizes(b, bufSizes, func(b *testing.B, n int) {
   225  		x := make([]byte, n)
   226  		y := make([]byte, n+1)
   227  		for i := 0; i < b.N; i++ {
   228  			copy(x, y[1:])
   229  		}
   230  	})
   231  }
   232  
   233  func TestMemclr(t *testing.T) {
   234  	size := 512
   235  	if testing.Short() {
   236  		size = 128 + 16
   237  	}
   238  	mem := make([]byte, size)
   239  	for i := 0; i < size; i++ {
   240  		mem[i] = 0xee
   241  	}
   242  	for n := 0; n < size; n++ {
   243  		for x := 0; x <= size-n; x++ { // offset in mem
   244  			MemclrBytes(mem[x : x+n])
   245  			for i := 0; i < x; i++ {
   246  				if mem[i] != 0xee {
   247  					t.Fatalf("overwrite prefix mem[%d] = %d", i, mem[i])
   248  				}
   249  			}
   250  			for i := x; i < x+n; i++ {
   251  				if mem[i] != 0 {
   252  					t.Fatalf("failed clear mem[%d] = %d", i, mem[i])
   253  				}
   254  				mem[i] = 0xee
   255  			}
   256  			for i := x + n; i < size; i++ {
   257  				if mem[i] != 0xee {
   258  					t.Fatalf("overwrite suffix mem[%d] = %d", i, mem[i])
   259  				}
   260  			}
   261  		}
   262  	}
   263  }
   264  
   265  func BenchmarkMemclr(b *testing.B) {
   266  	for _, n := range []int{5, 16, 64, 256, 4096, 65536} {
   267  		x := make([]byte, n)
   268  		b.Run(fmt.Sprint(n), func(b *testing.B) {
   269  			b.SetBytes(int64(n))
   270  			for i := 0; i < b.N; i++ {
   271  				MemclrBytes(x)
   272  			}
   273  		})
   274  	}
   275  	for _, m := range []int{1, 4, 8, 16, 64} {
   276  		x := make([]byte, m<<20)
   277  		b.Run(fmt.Sprint(m, "M"), func(b *testing.B) {
   278  			b.SetBytes(int64(m << 20))
   279  			for i := 0; i < b.N; i++ {
   280  				MemclrBytes(x)
   281  			}
   282  		})
   283  	}
   284  }
   285  
   286  func BenchmarkGoMemclr(b *testing.B) {
   287  	benchmarkSizes(b, []int{5, 16, 64, 256}, func(b *testing.B, n int) {
   288  		x := make([]byte, n)
   289  		for i := 0; i < b.N; i++ {
   290  			for j := range x {
   291  				x[j] = 0
   292  			}
   293  		}
   294  	})
   295  }
   296  
   297  func BenchmarkClearFat8(b *testing.B) {
   298  	for i := 0; i < b.N; i++ {
   299  		var x [8 / 4]uint32
   300  		_ = x
   301  	}
   302  }
   303  func BenchmarkClearFat12(b *testing.B) {
   304  	for i := 0; i < b.N; i++ {
   305  		var x [12 / 4]uint32
   306  		_ = x
   307  	}
   308  }
   309  func BenchmarkClearFat16(b *testing.B) {
   310  	for i := 0; i < b.N; i++ {
   311  		var x [16 / 4]uint32
   312  		_ = x
   313  	}
   314  }
   315  func BenchmarkClearFat24(b *testing.B) {
   316  	for i := 0; i < b.N; i++ {
   317  		var x [24 / 4]uint32
   318  		_ = x
   319  	}
   320  }
   321  func BenchmarkClearFat32(b *testing.B) {
   322  	for i := 0; i < b.N; i++ {
   323  		var x [32 / 4]uint32
   324  		_ = x
   325  	}
   326  }
   327  func BenchmarkClearFat40(b *testing.B) {
   328  	for i := 0; i < b.N; i++ {
   329  		var x [40 / 4]uint32
   330  		_ = x
   331  	}
   332  }
   333  func BenchmarkClearFat48(b *testing.B) {
   334  	for i := 0; i < b.N; i++ {
   335  		var x [48 / 4]uint32
   336  		_ = x
   337  	}
   338  }
   339  func BenchmarkClearFat56(b *testing.B) {
   340  	for i := 0; i < b.N; i++ {
   341  		var x [56 / 4]uint32
   342  		_ = x
   343  	}
   344  }
   345  func BenchmarkClearFat64(b *testing.B) {
   346  	for i := 0; i < b.N; i++ {
   347  		var x [64 / 4]uint32
   348  		_ = x
   349  	}
   350  }
   351  func BenchmarkClearFat128(b *testing.B) {
   352  	for i := 0; i < b.N; i++ {
   353  		var x [128 / 4]uint32
   354  		_ = x
   355  	}
   356  }
   357  func BenchmarkClearFat256(b *testing.B) {
   358  	for i := 0; i < b.N; i++ {
   359  		var x [256 / 4]uint32
   360  		_ = x
   361  	}
   362  }
   363  func BenchmarkClearFat512(b *testing.B) {
   364  	for i := 0; i < b.N; i++ {
   365  		var x [512 / 4]uint32
   366  		_ = x
   367  	}
   368  }
   369  func BenchmarkClearFat1024(b *testing.B) {
   370  	for i := 0; i < b.N; i++ {
   371  		var x [1024 / 4]uint32
   372  		_ = x
   373  	}
   374  }
   375  
   376  func BenchmarkCopyFat8(b *testing.B) {
   377  	var x [8 / 4]uint32
   378  	for i := 0; i < b.N; i++ {
   379  		y := x
   380  		_ = y
   381  	}
   382  }
   383  func BenchmarkCopyFat12(b *testing.B) {
   384  	var x [12 / 4]uint32
   385  	for i := 0; i < b.N; i++ {
   386  		y := x
   387  		_ = y
   388  	}
   389  }
   390  func BenchmarkCopyFat16(b *testing.B) {
   391  	var x [16 / 4]uint32
   392  	for i := 0; i < b.N; i++ {
   393  		y := x
   394  		_ = y
   395  	}
   396  }
   397  func BenchmarkCopyFat24(b *testing.B) {
   398  	var x [24 / 4]uint32
   399  	for i := 0; i < b.N; i++ {
   400  		y := x
   401  		_ = y
   402  	}
   403  }
   404  func BenchmarkCopyFat32(b *testing.B) {
   405  	var x [32 / 4]uint32
   406  	for i := 0; i < b.N; i++ {
   407  		y := x
   408  		_ = y
   409  	}
   410  }
   411  func BenchmarkCopyFat64(b *testing.B) {
   412  	var x [64 / 4]uint32
   413  	for i := 0; i < b.N; i++ {
   414  		y := x
   415  		_ = y
   416  	}
   417  }
   418  func BenchmarkCopyFat128(b *testing.B) {
   419  	var x [128 / 4]uint32
   420  	for i := 0; i < b.N; i++ {
   421  		y := x
   422  		_ = y
   423  	}
   424  }
   425  func BenchmarkCopyFat256(b *testing.B) {
   426  	var x [256 / 4]uint32
   427  	for i := 0; i < b.N; i++ {
   428  		y := x
   429  		_ = y
   430  	}
   431  }
   432  func BenchmarkCopyFat512(b *testing.B) {
   433  	var x [512 / 4]uint32
   434  	for i := 0; i < b.N; i++ {
   435  		y := x
   436  		_ = y
   437  	}
   438  }
   439  func BenchmarkCopyFat1024(b *testing.B) {
   440  	var x [1024 / 4]uint32
   441  	for i := 0; i < b.N; i++ {
   442  		y := x
   443  		_ = y
   444  	}
   445  }