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 }