github.com/twelsh-aw/go/src@v0.0.0-20230516233729-a56fe86a7c81/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 "encoding/binary" 10 "fmt" 11 "internal/race" 12 "internal/testenv" 13 . "runtime" 14 "sync/atomic" 15 "testing" 16 "unsafe" 17 ) 18 19 func TestMemmove(t *testing.T) { 20 if *flagQuick { 21 t.Skip("-quick") 22 } 23 t.Parallel() 24 size := 256 25 if testing.Short() { 26 size = 128 + 16 27 } 28 src := make([]byte, size) 29 dst := make([]byte, size) 30 for i := 0; i < size; i++ { 31 src[i] = byte(128 + (i & 127)) 32 } 33 for i := 0; i < size; i++ { 34 dst[i] = byte(i & 127) 35 } 36 for n := 0; n <= size; n++ { 37 for x := 0; x <= size-n; x++ { // offset in src 38 for y := 0; y <= size-n; y++ { // offset in dst 39 copy(dst[y:y+n], src[x:x+n]) 40 for i := 0; i < y; i++ { 41 if dst[i] != byte(i&127) { 42 t.Fatalf("prefix dst[%d] = %d", i, dst[i]) 43 } 44 } 45 for i := y; i < y+n; i++ { 46 if dst[i] != byte(128+((i-y+x)&127)) { 47 t.Fatalf("copied dst[%d] = %d", i, dst[i]) 48 } 49 dst[i] = byte(i & 127) // reset dst 50 } 51 for i := y + n; i < size; i++ { 52 if dst[i] != byte(i&127) { 53 t.Fatalf("suffix dst[%d] = %d", i, dst[i]) 54 } 55 } 56 } 57 } 58 } 59 } 60 61 func TestMemmoveAlias(t *testing.T) { 62 if *flagQuick { 63 t.Skip("-quick") 64 } 65 t.Parallel() 66 size := 256 67 if testing.Short() { 68 size = 128 + 16 69 } 70 buf := make([]byte, size) 71 for i := 0; i < size; i++ { 72 buf[i] = byte(i) 73 } 74 for n := 0; n <= size; n++ { 75 for x := 0; x <= size-n; x++ { // src offset 76 for y := 0; y <= size-n; y++ { // dst offset 77 copy(buf[y:y+n], buf[x:x+n]) 78 for i := 0; i < y; i++ { 79 if buf[i] != byte(i) { 80 t.Fatalf("prefix buf[%d] = %d", i, buf[i]) 81 } 82 } 83 for i := y; i < y+n; i++ { 84 if buf[i] != byte(i-y+x) { 85 t.Fatalf("copied buf[%d] = %d", i, buf[i]) 86 } 87 buf[i] = byte(i) // reset buf 88 } 89 for i := y + n; i < size; i++ { 90 if buf[i] != byte(i) { 91 t.Fatalf("suffix buf[%d] = %d", i, buf[i]) 92 } 93 } 94 } 95 } 96 } 97 } 98 99 func TestMemmoveLarge0x180000(t *testing.T) { 100 if testing.Short() && testenv.Builder() == "" { 101 t.Skip("-short") 102 } 103 104 t.Parallel() 105 if race.Enabled { 106 t.Skip("skipping large memmove test under race detector") 107 } 108 testSize(t, 0x180000) 109 } 110 111 func TestMemmoveOverlapLarge0x120000(t *testing.T) { 112 if testing.Short() && testenv.Builder() == "" { 113 t.Skip("-short") 114 } 115 116 t.Parallel() 117 if race.Enabled { 118 t.Skip("skipping large memmove test under race detector") 119 } 120 testOverlap(t, 0x120000) 121 } 122 123 func testSize(t *testing.T, size int) { 124 src := make([]byte, size) 125 dst := make([]byte, size) 126 _, _ = rand.Read(src) 127 _, _ = rand.Read(dst) 128 129 ref := make([]byte, size) 130 copyref(ref, dst) 131 132 for n := size - 50; n > 1; n >>= 1 { 133 for x := 0; x <= size-n; x = x*7 + 1 { // offset in src 134 for y := 0; y <= size-n; y = y*9 + 1 { // offset in dst 135 copy(dst[y:y+n], src[x:x+n]) 136 copyref(ref[y:y+n], src[x:x+n]) 137 p := cmpb(dst, ref) 138 if p >= 0 { 139 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]) 140 } 141 } 142 } 143 } 144 } 145 146 func testOverlap(t *testing.T, size int) { 147 src := make([]byte, size) 148 test := make([]byte, size) 149 ref := make([]byte, size) 150 _, _ = rand.Read(src) 151 152 for n := size - 50; n > 1; n >>= 1 { 153 for x := 0; x <= size-n; x = x*7 + 1 { // offset in src 154 for y := 0; y <= size-n; y = y*9 + 1 { // offset in dst 155 // Reset input 156 copyref(test, src) 157 copyref(ref, src) 158 copy(test[y:y+n], test[x:x+n]) 159 if y <= x { 160 copyref(ref[y:y+n], ref[x:x+n]) 161 } else { 162 copybw(ref[y:y+n], ref[x:x+n]) 163 } 164 p := cmpb(test, ref) 165 if p >= 0 { 166 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]) 167 } 168 } 169 } 170 } 171 172 } 173 174 // Forward copy. 175 func copyref(dst, src []byte) { 176 for i, v := range src { 177 dst[i] = v 178 } 179 } 180 181 // Backwards copy 182 func copybw(dst, src []byte) { 183 if len(src) == 0 { 184 return 185 } 186 for i := len(src) - 1; i >= 0; i-- { 187 dst[i] = src[i] 188 } 189 } 190 191 // Returns offset of difference 192 func matchLen(a, b []byte, max int) int { 193 a = a[:max] 194 b = b[:max] 195 for i, av := range a { 196 if b[i] != av { 197 return i 198 } 199 } 200 return max 201 } 202 203 func cmpb(a, b []byte) int { 204 l := matchLen(a, b, len(a)) 205 if l == len(a) { 206 return -1 207 } 208 return l 209 } 210 211 // Ensure that memmove writes pointers atomically, so the GC won't 212 // observe a partially updated pointer. 213 func TestMemmoveAtomicity(t *testing.T) { 214 if race.Enabled { 215 t.Skip("skip under the race detector -- this test is intentionally racy") 216 } 217 218 var x int 219 220 for _, backward := range []bool{true, false} { 221 for _, n := range []int{3, 4, 5, 6, 7, 8, 9, 10, 15, 25, 49} { 222 n := n 223 224 // test copying [N]*int. 225 sz := uintptr(n * PtrSize) 226 name := fmt.Sprint(sz) 227 if backward { 228 name += "-backward" 229 } else { 230 name += "-forward" 231 } 232 t.Run(name, func(t *testing.T) { 233 // Use overlapping src and dst to force forward/backward copy. 234 var s [100]*int 235 src := s[n-1 : 2*n-1] 236 dst := s[:n] 237 if backward { 238 src, dst = dst, src 239 } 240 for i := range src { 241 src[i] = &x 242 } 243 for i := range dst { 244 dst[i] = nil 245 } 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 for i := 0; i < b.N; i++ { 298 copy(x, y) 299 } 300 }) 301 } 302 303 func BenchmarkMemmoveOverlap(b *testing.B) { 304 benchmarkSizes(b, bufSizesOverlap, func(b *testing.B, n int) { 305 x := make([]byte, n+16) 306 for i := 0; i < b.N; i++ { 307 copy(x[16:n+16], x[:n]) 308 } 309 }) 310 } 311 312 func BenchmarkMemmoveUnalignedDst(b *testing.B) { 313 benchmarkSizes(b, bufSizes, func(b *testing.B, n int) { 314 x := make([]byte, n+1) 315 y := make([]byte, n) 316 for i := 0; i < b.N; i++ { 317 copy(x[1:], y) 318 } 319 }) 320 } 321 322 func BenchmarkMemmoveUnalignedDstOverlap(b *testing.B) { 323 benchmarkSizes(b, bufSizesOverlap, func(b *testing.B, n int) { 324 x := make([]byte, n+16) 325 for i := 0; i < b.N; i++ { 326 copy(x[16:n+16], x[1:n+1]) 327 } 328 }) 329 } 330 331 func BenchmarkMemmoveUnalignedSrc(b *testing.B) { 332 benchmarkSizes(b, bufSizes, func(b *testing.B, n int) { 333 x := make([]byte, n) 334 y := make([]byte, n+1) 335 for i := 0; i < b.N; i++ { 336 copy(x, y[1:]) 337 } 338 }) 339 } 340 341 func BenchmarkMemmoveUnalignedSrcOverlap(b *testing.B) { 342 benchmarkSizes(b, bufSizesOverlap, func(b *testing.B, n int) { 343 x := make([]byte, n+1) 344 for i := 0; i < b.N; i++ { 345 copy(x[1:n+1], x[:n]) 346 } 347 }) 348 } 349 350 func TestMemclr(t *testing.T) { 351 size := 512 352 if testing.Short() { 353 size = 128 + 16 354 } 355 mem := make([]byte, size) 356 for i := 0; i < size; i++ { 357 mem[i] = 0xee 358 } 359 for n := 0; n < size; n++ { 360 for x := 0; x <= size-n; x++ { // offset in mem 361 MemclrBytes(mem[x : x+n]) 362 for i := 0; i < x; i++ { 363 if mem[i] != 0xee { 364 t.Fatalf("overwrite prefix mem[%d] = %d", i, mem[i]) 365 } 366 } 367 for i := x; i < x+n; i++ { 368 if mem[i] != 0 { 369 t.Fatalf("failed clear mem[%d] = %d", i, mem[i]) 370 } 371 mem[i] = 0xee 372 } 373 for i := x + n; i < size; i++ { 374 if mem[i] != 0xee { 375 t.Fatalf("overwrite suffix mem[%d] = %d", i, mem[i]) 376 } 377 } 378 } 379 } 380 } 381 382 func BenchmarkMemclr(b *testing.B) { 383 for _, n := range []int{5, 16, 64, 256, 4096, 65536} { 384 x := make([]byte, n) 385 b.Run(fmt.Sprint(n), func(b *testing.B) { 386 b.SetBytes(int64(n)) 387 for i := 0; i < b.N; i++ { 388 MemclrBytes(x) 389 } 390 }) 391 } 392 for _, m := range []int{1, 4, 8, 16, 64} { 393 x := make([]byte, m<<20) 394 b.Run(fmt.Sprint(m, "M"), func(b *testing.B) { 395 b.SetBytes(int64(m << 20)) 396 for i := 0; i < b.N; i++ { 397 MemclrBytes(x) 398 } 399 }) 400 } 401 } 402 403 func BenchmarkGoMemclr(b *testing.B) { 404 benchmarkSizes(b, []int{5, 16, 64, 256}, func(b *testing.B, n int) { 405 x := make([]byte, n) 406 for i := 0; i < b.N; i++ { 407 for j := range x { 408 x[j] = 0 409 } 410 } 411 }) 412 } 413 414 func BenchmarkMemclrRange(b *testing.B) { 415 type RunData struct { 416 data []int 417 } 418 419 benchSizes := []RunData{ 420 {[]int{1043, 1078, 1894, 1582, 1044, 1165, 1467, 1100, 1919, 1562, 1932, 1645, 421 1412, 1038, 1576, 1200, 1029, 1336, 1095, 1494, 1350, 1025, 1502, 1548, 1316, 1296, 422 1868, 1639, 1546, 1626, 1642, 1308, 1726, 1665, 1678, 1187, 1515, 1598, 1353, 1237, 423 1977, 1452, 2012, 1914, 1514, 1136, 1975, 1618, 1536, 1695, 1600, 1733, 1392, 1099, 424 1358, 1996, 1224, 1783, 1197, 1838, 1460, 1556, 1554, 2020}}, // 1kb-2kb 425 {[]int{3964, 5139, 6573, 7775, 6553, 2413, 3466, 5394, 2469, 7336, 7091, 6745, 426 4028, 5643, 6164, 3475, 4138, 6908, 7559, 3335, 5660, 4122, 3945, 2082, 7564, 6584, 427 5111, 2288, 6789, 2797, 4928, 7986, 5163, 5447, 2999, 4968, 3174, 3202, 7908, 8137, 428 4735, 6161, 4646, 7592, 3083, 5329, 3687, 2754, 3599, 7231, 6455, 2549, 8063, 2189, 429 7121, 5048, 4277, 6626, 6306, 2815, 7473, 3963, 7549, 7255}}, // 2kb-8kb 430 {[]int{16304, 15936, 15760, 4736, 9136, 11184, 10160, 5952, 14560, 15744, 431 6624, 5872, 13088, 14656, 14192, 10304, 4112, 10384, 9344, 4496, 11392, 7024, 432 5200, 10064, 14784, 5808, 13504, 10480, 8512, 4896, 13264, 5600}}, // 4kb-16kb 433 {[]int{164576, 233136, 220224, 183280, 214112, 217248, 228560, 201728}}, // 128kb-256kb 434 } 435 436 for _, t := range benchSizes { 437 total := 0 438 minLen := 0 439 maxLen := 0 440 441 for _, clrLen := range t.data { 442 if clrLen > maxLen { 443 maxLen = clrLen 444 } 445 if clrLen < minLen || minLen == 0 { 446 minLen = clrLen 447 } 448 total += clrLen 449 } 450 buffer := make([]byte, maxLen) 451 452 text := "" 453 if minLen >= (1 << 20) { 454 text = fmt.Sprint(minLen>>20, "M ", (maxLen+(1<<20-1))>>20, "M") 455 } else if minLen >= (1 << 10) { 456 text = fmt.Sprint(minLen>>10, "K ", (maxLen+(1<<10-1))>>10, "K") 457 } else { 458 text = fmt.Sprint(minLen, " ", maxLen) 459 } 460 b.Run(text, func(b *testing.B) { 461 b.SetBytes(int64(total)) 462 for i := 0; i < b.N; i++ { 463 for _, clrLen := range t.data { 464 MemclrBytes(buffer[:clrLen]) 465 } 466 } 467 }) 468 } 469 } 470 471 func BenchmarkClearFat7(b *testing.B) { 472 p := new([7]byte) 473 Escape(p) 474 b.ResetTimer() 475 for i := 0; i < b.N; i++ { 476 *p = [7]byte{} 477 } 478 } 479 480 func BenchmarkClearFat8(b *testing.B) { 481 p := new([8 / 4]uint32) 482 Escape(p) 483 b.ResetTimer() 484 for i := 0; i < b.N; i++ { 485 *p = [8 / 4]uint32{} 486 } 487 } 488 489 func BenchmarkClearFat11(b *testing.B) { 490 p := new([11]byte) 491 Escape(p) 492 b.ResetTimer() 493 for i := 0; i < b.N; i++ { 494 *p = [11]byte{} 495 } 496 } 497 498 func BenchmarkClearFat12(b *testing.B) { 499 p := new([12 / 4]uint32) 500 Escape(p) 501 b.ResetTimer() 502 for i := 0; i < b.N; i++ { 503 *p = [12 / 4]uint32{} 504 } 505 } 506 507 func BenchmarkClearFat13(b *testing.B) { 508 p := new([13]byte) 509 Escape(p) 510 b.ResetTimer() 511 for i := 0; i < b.N; i++ { 512 *p = [13]byte{} 513 } 514 } 515 516 func BenchmarkClearFat14(b *testing.B) { 517 p := new([14]byte) 518 Escape(p) 519 b.ResetTimer() 520 for i := 0; i < b.N; i++ { 521 *p = [14]byte{} 522 } 523 } 524 525 func BenchmarkClearFat15(b *testing.B) { 526 p := new([15]byte) 527 Escape(p) 528 b.ResetTimer() 529 for i := 0; i < b.N; i++ { 530 *p = [15]byte{} 531 } 532 } 533 534 func BenchmarkClearFat16(b *testing.B) { 535 p := new([16 / 4]uint32) 536 Escape(p) 537 b.ResetTimer() 538 for i := 0; i < b.N; i++ { 539 *p = [16 / 4]uint32{} 540 } 541 } 542 543 func BenchmarkClearFat24(b *testing.B) { 544 p := new([24 / 4]uint32) 545 Escape(p) 546 b.ResetTimer() 547 for i := 0; i < b.N; i++ { 548 *p = [24 / 4]uint32{} 549 } 550 } 551 552 func BenchmarkClearFat32(b *testing.B) { 553 p := new([32 / 4]uint32) 554 Escape(p) 555 b.ResetTimer() 556 for i := 0; i < b.N; i++ { 557 *p = [32 / 4]uint32{} 558 } 559 } 560 561 func BenchmarkClearFat40(b *testing.B) { 562 p := new([40 / 4]uint32) 563 Escape(p) 564 b.ResetTimer() 565 for i := 0; i < b.N; i++ { 566 *p = [40 / 4]uint32{} 567 } 568 } 569 570 func BenchmarkClearFat48(b *testing.B) { 571 p := new([48 / 4]uint32) 572 Escape(p) 573 b.ResetTimer() 574 for i := 0; i < b.N; i++ { 575 *p = [48 / 4]uint32{} 576 } 577 } 578 579 func BenchmarkClearFat56(b *testing.B) { 580 p := new([56 / 4]uint32) 581 Escape(p) 582 b.ResetTimer() 583 for i := 0; i < b.N; i++ { 584 *p = [56 / 4]uint32{} 585 } 586 } 587 588 func BenchmarkClearFat64(b *testing.B) { 589 p := new([64 / 4]uint32) 590 Escape(p) 591 b.ResetTimer() 592 for i := 0; i < b.N; i++ { 593 *p = [64 / 4]uint32{} 594 } 595 } 596 597 func BenchmarkClearFat72(b *testing.B) { 598 p := new([72 / 4]uint32) 599 Escape(p) 600 b.ResetTimer() 601 for i := 0; i < b.N; i++ { 602 *p = [72 / 4]uint32{} 603 } 604 } 605 606 func BenchmarkClearFat128(b *testing.B) { 607 p := new([128 / 4]uint32) 608 Escape(p) 609 b.ResetTimer() 610 for i := 0; i < b.N; i++ { 611 *p = [128 / 4]uint32{} 612 } 613 } 614 615 func BenchmarkClearFat256(b *testing.B) { 616 p := new([256 / 4]uint32) 617 Escape(p) 618 b.ResetTimer() 619 for i := 0; i < b.N; i++ { 620 *p = [256 / 4]uint32{} 621 } 622 } 623 624 func BenchmarkClearFat512(b *testing.B) { 625 p := new([512 / 4]uint32) 626 Escape(p) 627 b.ResetTimer() 628 for i := 0; i < b.N; i++ { 629 *p = [512 / 4]uint32{} 630 } 631 } 632 633 func BenchmarkClearFat1024(b *testing.B) { 634 p := new([1024 / 4]uint32) 635 Escape(p) 636 b.ResetTimer() 637 for i := 0; i < b.N; i++ { 638 *p = [1024 / 4]uint32{} 639 } 640 } 641 642 func BenchmarkClearFat1032(b *testing.B) { 643 p := new([1032 / 4]uint32) 644 Escape(p) 645 b.ResetTimer() 646 for i := 0; i < b.N; i++ { 647 *p = [1032 / 4]uint32{} 648 } 649 } 650 651 func BenchmarkClearFat1040(b *testing.B) { 652 p := new([1040 / 4]uint32) 653 Escape(p) 654 b.ResetTimer() 655 for i := 0; i < b.N; i++ { 656 *p = [1040 / 4]uint32{} 657 } 658 } 659 660 func BenchmarkCopyFat7(b *testing.B) { 661 var x [7]byte 662 p := new([7]byte) 663 Escape(p) 664 b.ResetTimer() 665 for i := 0; i < b.N; i++ { 666 *p = x 667 } 668 } 669 670 func BenchmarkCopyFat8(b *testing.B) { 671 var x [8 / 4]uint32 672 p := new([8 / 4]uint32) 673 Escape(p) 674 b.ResetTimer() 675 for i := 0; i < b.N; i++ { 676 *p = x 677 } 678 } 679 680 func BenchmarkCopyFat11(b *testing.B) { 681 var x [11]byte 682 p := new([11]byte) 683 Escape(p) 684 b.ResetTimer() 685 for i := 0; i < b.N; i++ { 686 *p = x 687 } 688 } 689 690 func BenchmarkCopyFat12(b *testing.B) { 691 var x [12 / 4]uint32 692 p := new([12 / 4]uint32) 693 Escape(p) 694 b.ResetTimer() 695 for i := 0; i < b.N; i++ { 696 *p = x 697 } 698 } 699 700 func BenchmarkCopyFat13(b *testing.B) { 701 var x [13]byte 702 p := new([13]byte) 703 Escape(p) 704 b.ResetTimer() 705 for i := 0; i < b.N; i++ { 706 *p = x 707 } 708 } 709 710 func BenchmarkCopyFat14(b *testing.B) { 711 var x [14]byte 712 p := new([14]byte) 713 Escape(p) 714 b.ResetTimer() 715 for i := 0; i < b.N; i++ { 716 *p = x 717 } 718 } 719 720 func BenchmarkCopyFat15(b *testing.B) { 721 var x [15]byte 722 p := new([15]byte) 723 Escape(p) 724 b.ResetTimer() 725 for i := 0; i < b.N; i++ { 726 *p = x 727 } 728 } 729 730 func BenchmarkCopyFat16(b *testing.B) { 731 var x [16 / 4]uint32 732 p := new([16 / 4]uint32) 733 Escape(p) 734 b.ResetTimer() 735 for i := 0; i < b.N; i++ { 736 *p = x 737 } 738 } 739 740 func BenchmarkCopyFat24(b *testing.B) { 741 var x [24 / 4]uint32 742 p := new([24 / 4]uint32) 743 Escape(p) 744 b.ResetTimer() 745 for i := 0; i < b.N; i++ { 746 *p = x 747 } 748 } 749 750 func BenchmarkCopyFat32(b *testing.B) { 751 var x [32 / 4]uint32 752 p := new([32 / 4]uint32) 753 Escape(p) 754 b.ResetTimer() 755 for i := 0; i < b.N; i++ { 756 *p = x 757 } 758 } 759 760 func BenchmarkCopyFat64(b *testing.B) { 761 var x [64 / 4]uint32 762 p := new([64 / 4]uint32) 763 Escape(p) 764 b.ResetTimer() 765 for i := 0; i < b.N; i++ { 766 *p = x 767 } 768 } 769 770 func BenchmarkCopyFat72(b *testing.B) { 771 var x [72 / 4]uint32 772 p := new([72 / 4]uint32) 773 Escape(p) 774 b.ResetTimer() 775 for i := 0; i < b.N; i++ { 776 *p = x 777 } 778 } 779 780 func BenchmarkCopyFat128(b *testing.B) { 781 var x [128 / 4]uint32 782 p := new([128 / 4]uint32) 783 Escape(p) 784 b.ResetTimer() 785 for i := 0; i < b.N; i++ { 786 *p = x 787 } 788 } 789 790 func BenchmarkCopyFat256(b *testing.B) { 791 var x [256 / 4]uint32 792 p := new([256 / 4]uint32) 793 Escape(p) 794 b.ResetTimer() 795 for i := 0; i < b.N; i++ { 796 *p = x 797 } 798 } 799 800 func BenchmarkCopyFat512(b *testing.B) { 801 var x [512 / 4]uint32 802 p := new([512 / 4]uint32) 803 Escape(p) 804 b.ResetTimer() 805 for i := 0; i < b.N; i++ { 806 *p = x 807 } 808 } 809 810 func BenchmarkCopyFat520(b *testing.B) { 811 var x [520 / 4]uint32 812 p := new([520 / 4]uint32) 813 Escape(p) 814 b.ResetTimer() 815 for i := 0; i < b.N; i++ { 816 *p = x 817 } 818 } 819 820 func BenchmarkCopyFat1024(b *testing.B) { 821 var x [1024 / 4]uint32 822 p := new([1024 / 4]uint32) 823 Escape(p) 824 b.ResetTimer() 825 for i := 0; i < b.N; i++ { 826 *p = x 827 } 828 } 829 830 func BenchmarkCopyFat1032(b *testing.B) { 831 var x [1032 / 4]uint32 832 p := new([1032 / 4]uint32) 833 Escape(p) 834 b.ResetTimer() 835 for i := 0; i < b.N; i++ { 836 *p = x 837 } 838 } 839 840 func BenchmarkCopyFat1040(b *testing.B) { 841 var x [1040 / 4]uint32 842 p := new([1040 / 4]uint32) 843 Escape(p) 844 b.ResetTimer() 845 for i := 0; i < b.N; i++ { 846 *p = x 847 } 848 } 849 850 // BenchmarkIssue18740 ensures that memmove uses 4 and 8 byte load/store to move 4 and 8 bytes. 851 // It used to do 2 2-byte load/stores, which leads to a pipeline stall 852 // when we try to read the result with one 4-byte load. 853 func BenchmarkIssue18740(b *testing.B) { 854 benchmarks := []struct { 855 name string 856 nbyte int 857 f func([]byte) uint64 858 }{ 859 {"2byte", 2, func(buf []byte) uint64 { return uint64(binary.LittleEndian.Uint16(buf)) }}, 860 {"4byte", 4, func(buf []byte) uint64 { return uint64(binary.LittleEndian.Uint32(buf)) }}, 861 {"8byte", 8, func(buf []byte) uint64 { return binary.LittleEndian.Uint64(buf) }}, 862 } 863 864 var g [4096]byte 865 for _, bm := range benchmarks { 866 buf := make([]byte, bm.nbyte) 867 b.Run(bm.name, func(b *testing.B) { 868 for j := 0; j < b.N; j++ { 869 for i := 0; i < 4096; i += bm.nbyte { 870 copy(buf[:], g[i:]) 871 sink += bm.f(buf[:]) 872 } 873 } 874 }) 875 } 876 } 877 878 var memclrSink []int8 879 880 func BenchmarkMemclrKnownSize1(b *testing.B) { 881 var x [1]int8 882 883 b.SetBytes(1) 884 for i := 0; i < b.N; i++ { 885 for a := range x { 886 x[a] = 0 887 } 888 } 889 890 memclrSink = x[:] 891 } 892 func BenchmarkMemclrKnownSize2(b *testing.B) { 893 var x [2]int8 894 895 b.SetBytes(2) 896 for i := 0; i < b.N; i++ { 897 for a := range x { 898 x[a] = 0 899 } 900 } 901 902 memclrSink = x[:] 903 } 904 func BenchmarkMemclrKnownSize4(b *testing.B) { 905 var x [4]int8 906 907 b.SetBytes(4) 908 for i := 0; i < b.N; i++ { 909 for a := range x { 910 x[a] = 0 911 } 912 } 913 914 memclrSink = x[:] 915 } 916 func BenchmarkMemclrKnownSize8(b *testing.B) { 917 var x [8]int8 918 919 b.SetBytes(8) 920 for i := 0; i < b.N; i++ { 921 for a := range x { 922 x[a] = 0 923 } 924 } 925 926 memclrSink = x[:] 927 } 928 func BenchmarkMemclrKnownSize16(b *testing.B) { 929 var x [16]int8 930 931 b.SetBytes(16) 932 for i := 0; i < b.N; i++ { 933 for a := range x { 934 x[a] = 0 935 } 936 } 937 938 memclrSink = x[:] 939 } 940 func BenchmarkMemclrKnownSize32(b *testing.B) { 941 var x [32]int8 942 943 b.SetBytes(32) 944 for i := 0; i < b.N; i++ { 945 for a := range x { 946 x[a] = 0 947 } 948 } 949 950 memclrSink = x[:] 951 } 952 func BenchmarkMemclrKnownSize64(b *testing.B) { 953 var x [64]int8 954 955 b.SetBytes(64) 956 for i := 0; i < b.N; i++ { 957 for a := range x { 958 x[a] = 0 959 } 960 } 961 962 memclrSink = x[:] 963 } 964 func BenchmarkMemclrKnownSize112(b *testing.B) { 965 var x [112]int8 966 967 b.SetBytes(112) 968 for i := 0; i < b.N; i++ { 969 for a := range x { 970 x[a] = 0 971 } 972 } 973 974 memclrSink = x[:] 975 } 976 977 func BenchmarkMemclrKnownSize128(b *testing.B) { 978 var x [128]int8 979 980 b.SetBytes(128) 981 for i := 0; i < b.N; i++ { 982 for a := range x { 983 x[a] = 0 984 } 985 } 986 987 memclrSink = x[:] 988 } 989 990 func BenchmarkMemclrKnownSize192(b *testing.B) { 991 var x [192]int8 992 993 b.SetBytes(192) 994 for i := 0; i < b.N; i++ { 995 for a := range x { 996 x[a] = 0 997 } 998 } 999 1000 memclrSink = x[:] 1001 } 1002 1003 func BenchmarkMemclrKnownSize248(b *testing.B) { 1004 var x [248]int8 1005 1006 b.SetBytes(248) 1007 for i := 0; i < b.N; i++ { 1008 for a := range x { 1009 x[a] = 0 1010 } 1011 } 1012 1013 memclrSink = x[:] 1014 } 1015 1016 func BenchmarkMemclrKnownSize256(b *testing.B) { 1017 var x [256]int8 1018 1019 b.SetBytes(256) 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 func BenchmarkMemclrKnownSize512(b *testing.B) { 1029 var x [512]int8 1030 1031 b.SetBytes(512) 1032 for i := 0; i < b.N; i++ { 1033 for a := range x { 1034 x[a] = 0 1035 } 1036 } 1037 1038 memclrSink = x[:] 1039 } 1040 func BenchmarkMemclrKnownSize1024(b *testing.B) { 1041 var x [1024]int8 1042 1043 b.SetBytes(1024) 1044 for i := 0; i < b.N; i++ { 1045 for a := range x { 1046 x[a] = 0 1047 } 1048 } 1049 1050 memclrSink = x[:] 1051 } 1052 func BenchmarkMemclrKnownSize4096(b *testing.B) { 1053 var x [4096]int8 1054 1055 b.SetBytes(4096) 1056 for i := 0; i < b.N; i++ { 1057 for a := range x { 1058 x[a] = 0 1059 } 1060 } 1061 1062 memclrSink = x[:] 1063 } 1064 func BenchmarkMemclrKnownSize512KiB(b *testing.B) { 1065 var x [524288]int8 1066 1067 b.SetBytes(524288) 1068 for i := 0; i < b.N; i++ { 1069 for a := range x { 1070 x[a] = 0 1071 } 1072 } 1073 1074 memclrSink = x[:] 1075 }