github.com/ice-blockchain/go/src@v0.0.0-20240403114104-1564d284e521/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 BenchmarkMemmoveUnalignedSrcDst(b *testing.B) { 342 for _, n := range []int{16, 64, 256, 4096, 65536} { 343 buf := make([]byte, (n+8)*2) 344 x := buf[:len(buf)/2] 345 y := buf[len(buf)/2:] 346 for _, off := range []int{0, 1, 4, 7} { 347 b.Run(fmt.Sprint("f_", n, off), func(b *testing.B) { 348 b.SetBytes(int64(n)) 349 for i := 0; i < b.N; i++ { 350 copy(x[off:n+off], y[off:n+off]) 351 } 352 }) 353 354 b.Run(fmt.Sprint("b_", n, off), func(b *testing.B) { 355 b.SetBytes(int64(n)) 356 for i := 0; i < b.N; i++ { 357 copy(y[off:n+off], x[off:n+off]) 358 } 359 }) 360 } 361 } 362 } 363 364 func BenchmarkMemmoveUnalignedSrcOverlap(b *testing.B) { 365 benchmarkSizes(b, bufSizesOverlap, func(b *testing.B, n int) { 366 x := make([]byte, n+1) 367 for i := 0; i < b.N; i++ { 368 copy(x[1:n+1], x[:n]) 369 } 370 }) 371 } 372 373 func TestMemclr(t *testing.T) { 374 size := 512 375 if testing.Short() { 376 size = 128 + 16 377 } 378 mem := make([]byte, size) 379 for i := 0; i < size; i++ { 380 mem[i] = 0xee 381 } 382 for n := 0; n < size; n++ { 383 for x := 0; x <= size-n; x++ { // offset in mem 384 MemclrBytes(mem[x : x+n]) 385 for i := 0; i < x; i++ { 386 if mem[i] != 0xee { 387 t.Fatalf("overwrite prefix mem[%d] = %d", i, mem[i]) 388 } 389 } 390 for i := x; i < x+n; i++ { 391 if mem[i] != 0 { 392 t.Fatalf("failed clear mem[%d] = %d", i, mem[i]) 393 } 394 mem[i] = 0xee 395 } 396 for i := x + n; i < size; i++ { 397 if mem[i] != 0xee { 398 t.Fatalf("overwrite suffix mem[%d] = %d", i, mem[i]) 399 } 400 } 401 } 402 } 403 } 404 405 func BenchmarkMemclr(b *testing.B) { 406 for _, n := range []int{5, 16, 64, 256, 4096, 65536} { 407 x := make([]byte, n) 408 b.Run(fmt.Sprint(n), func(b *testing.B) { 409 b.SetBytes(int64(n)) 410 for i := 0; i < b.N; i++ { 411 MemclrBytes(x) 412 } 413 }) 414 } 415 for _, m := range []int{1, 4, 8, 16, 64} { 416 x := make([]byte, m<<20) 417 b.Run(fmt.Sprint(m, "M"), func(b *testing.B) { 418 b.SetBytes(int64(m << 20)) 419 for i := 0; i < b.N; i++ { 420 MemclrBytes(x) 421 } 422 }) 423 } 424 } 425 426 func BenchmarkMemclrUnaligned(b *testing.B) { 427 for _, off := range []int{0, 1, 4, 7} { 428 for _, n := range []int{5, 16, 64, 256, 4096, 65536} { 429 x := make([]byte, n+off) 430 b.Run(fmt.Sprint(off, n), func(b *testing.B) { 431 b.SetBytes(int64(n)) 432 for i := 0; i < b.N; i++ { 433 MemclrBytes(x[off:]) 434 } 435 }) 436 } 437 } 438 439 for _, off := range []int{0, 1, 4, 7} { 440 for _, m := range []int{1, 4, 8, 16, 64} { 441 x := make([]byte, (m<<20)+off) 442 b.Run(fmt.Sprint(off, m, "M"), func(b *testing.B) { 443 b.SetBytes(int64(m << 20)) 444 for i := 0; i < b.N; i++ { 445 MemclrBytes(x[off:]) 446 } 447 }) 448 } 449 } 450 } 451 452 func BenchmarkGoMemclr(b *testing.B) { 453 benchmarkSizes(b, []int{5, 16, 64, 256}, func(b *testing.B, n int) { 454 x := make([]byte, n) 455 for i := 0; i < b.N; i++ { 456 for j := range x { 457 x[j] = 0 458 } 459 } 460 }) 461 } 462 463 func BenchmarkMemclrRange(b *testing.B) { 464 type RunData struct { 465 data []int 466 } 467 468 benchSizes := []RunData{ 469 {[]int{1043, 1078, 1894, 1582, 1044, 1165, 1467, 1100, 1919, 1562, 1932, 1645, 470 1412, 1038, 1576, 1200, 1029, 1336, 1095, 1494, 1350, 1025, 1502, 1548, 1316, 1296, 471 1868, 1639, 1546, 1626, 1642, 1308, 1726, 1665, 1678, 1187, 1515, 1598, 1353, 1237, 472 1977, 1452, 2012, 1914, 1514, 1136, 1975, 1618, 1536, 1695, 1600, 1733, 1392, 1099, 473 1358, 1996, 1224, 1783, 1197, 1838, 1460, 1556, 1554, 2020}}, // 1kb-2kb 474 {[]int{3964, 5139, 6573, 7775, 6553, 2413, 3466, 5394, 2469, 7336, 7091, 6745, 475 4028, 5643, 6164, 3475, 4138, 6908, 7559, 3335, 5660, 4122, 3945, 2082, 7564, 6584, 476 5111, 2288, 6789, 2797, 4928, 7986, 5163, 5447, 2999, 4968, 3174, 3202, 7908, 8137, 477 4735, 6161, 4646, 7592, 3083, 5329, 3687, 2754, 3599, 7231, 6455, 2549, 8063, 2189, 478 7121, 5048, 4277, 6626, 6306, 2815, 7473, 3963, 7549, 7255}}, // 2kb-8kb 479 {[]int{16304, 15936, 15760, 4736, 9136, 11184, 10160, 5952, 14560, 15744, 480 6624, 5872, 13088, 14656, 14192, 10304, 4112, 10384, 9344, 4496, 11392, 7024, 481 5200, 10064, 14784, 5808, 13504, 10480, 8512, 4896, 13264, 5600}}, // 4kb-16kb 482 {[]int{164576, 233136, 220224, 183280, 214112, 217248, 228560, 201728}}, // 128kb-256kb 483 } 484 485 for _, t := range benchSizes { 486 total := 0 487 minLen := 0 488 maxLen := 0 489 490 for _, clrLen := range t.data { 491 maxLen = max(maxLen, clrLen) 492 if clrLen < minLen || minLen == 0 { 493 minLen = clrLen 494 } 495 total += clrLen 496 } 497 buffer := make([]byte, maxLen) 498 499 text := "" 500 if minLen >= (1 << 20) { 501 text = fmt.Sprint(minLen>>20, "M ", (maxLen+(1<<20-1))>>20, "M") 502 } else if minLen >= (1 << 10) { 503 text = fmt.Sprint(minLen>>10, "K ", (maxLen+(1<<10-1))>>10, "K") 504 } else { 505 text = fmt.Sprint(minLen, " ", maxLen) 506 } 507 b.Run(text, func(b *testing.B) { 508 b.SetBytes(int64(total)) 509 for i := 0; i < b.N; i++ { 510 for _, clrLen := range t.data { 511 MemclrBytes(buffer[:clrLen]) 512 } 513 } 514 }) 515 } 516 } 517 518 func BenchmarkClearFat7(b *testing.B) { 519 p := new([7]byte) 520 Escape(p) 521 b.ResetTimer() 522 for i := 0; i < b.N; i++ { 523 *p = [7]byte{} 524 } 525 } 526 527 func BenchmarkClearFat8(b *testing.B) { 528 p := new([8 / 4]uint32) 529 Escape(p) 530 b.ResetTimer() 531 for i := 0; i < b.N; i++ { 532 *p = [8 / 4]uint32{} 533 } 534 } 535 536 func BenchmarkClearFat11(b *testing.B) { 537 p := new([11]byte) 538 Escape(p) 539 b.ResetTimer() 540 for i := 0; i < b.N; i++ { 541 *p = [11]byte{} 542 } 543 } 544 545 func BenchmarkClearFat12(b *testing.B) { 546 p := new([12 / 4]uint32) 547 Escape(p) 548 b.ResetTimer() 549 for i := 0; i < b.N; i++ { 550 *p = [12 / 4]uint32{} 551 } 552 } 553 554 func BenchmarkClearFat13(b *testing.B) { 555 p := new([13]byte) 556 Escape(p) 557 b.ResetTimer() 558 for i := 0; i < b.N; i++ { 559 *p = [13]byte{} 560 } 561 } 562 563 func BenchmarkClearFat14(b *testing.B) { 564 p := new([14]byte) 565 Escape(p) 566 b.ResetTimer() 567 for i := 0; i < b.N; i++ { 568 *p = [14]byte{} 569 } 570 } 571 572 func BenchmarkClearFat15(b *testing.B) { 573 p := new([15]byte) 574 Escape(p) 575 b.ResetTimer() 576 for i := 0; i < b.N; i++ { 577 *p = [15]byte{} 578 } 579 } 580 581 func BenchmarkClearFat16(b *testing.B) { 582 p := new([16 / 4]uint32) 583 Escape(p) 584 b.ResetTimer() 585 for i := 0; i < b.N; i++ { 586 *p = [16 / 4]uint32{} 587 } 588 } 589 590 func BenchmarkClearFat24(b *testing.B) { 591 p := new([24 / 4]uint32) 592 Escape(p) 593 b.ResetTimer() 594 for i := 0; i < b.N; i++ { 595 *p = [24 / 4]uint32{} 596 } 597 } 598 599 func BenchmarkClearFat32(b *testing.B) { 600 p := new([32 / 4]uint32) 601 Escape(p) 602 b.ResetTimer() 603 for i := 0; i < b.N; i++ { 604 *p = [32 / 4]uint32{} 605 } 606 } 607 608 func BenchmarkClearFat40(b *testing.B) { 609 p := new([40 / 4]uint32) 610 Escape(p) 611 b.ResetTimer() 612 for i := 0; i < b.N; i++ { 613 *p = [40 / 4]uint32{} 614 } 615 } 616 617 func BenchmarkClearFat48(b *testing.B) { 618 p := new([48 / 4]uint32) 619 Escape(p) 620 b.ResetTimer() 621 for i := 0; i < b.N; i++ { 622 *p = [48 / 4]uint32{} 623 } 624 } 625 626 func BenchmarkClearFat56(b *testing.B) { 627 p := new([56 / 4]uint32) 628 Escape(p) 629 b.ResetTimer() 630 for i := 0; i < b.N; i++ { 631 *p = [56 / 4]uint32{} 632 } 633 } 634 635 func BenchmarkClearFat64(b *testing.B) { 636 p := new([64 / 4]uint32) 637 Escape(p) 638 b.ResetTimer() 639 for i := 0; i < b.N; i++ { 640 *p = [64 / 4]uint32{} 641 } 642 } 643 644 func BenchmarkClearFat72(b *testing.B) { 645 p := new([72 / 4]uint32) 646 Escape(p) 647 b.ResetTimer() 648 for i := 0; i < b.N; i++ { 649 *p = [72 / 4]uint32{} 650 } 651 } 652 653 func BenchmarkClearFat128(b *testing.B) { 654 p := new([128 / 4]uint32) 655 Escape(p) 656 b.ResetTimer() 657 for i := 0; i < b.N; i++ { 658 *p = [128 / 4]uint32{} 659 } 660 } 661 662 func BenchmarkClearFat256(b *testing.B) { 663 p := new([256 / 4]uint32) 664 Escape(p) 665 b.ResetTimer() 666 for i := 0; i < b.N; i++ { 667 *p = [256 / 4]uint32{} 668 } 669 } 670 671 func BenchmarkClearFat512(b *testing.B) { 672 p := new([512 / 4]uint32) 673 Escape(p) 674 b.ResetTimer() 675 for i := 0; i < b.N; i++ { 676 *p = [512 / 4]uint32{} 677 } 678 } 679 680 func BenchmarkClearFat1024(b *testing.B) { 681 p := new([1024 / 4]uint32) 682 Escape(p) 683 b.ResetTimer() 684 for i := 0; i < b.N; i++ { 685 *p = [1024 / 4]uint32{} 686 } 687 } 688 689 func BenchmarkClearFat1032(b *testing.B) { 690 p := new([1032 / 4]uint32) 691 Escape(p) 692 b.ResetTimer() 693 for i := 0; i < b.N; i++ { 694 *p = [1032 / 4]uint32{} 695 } 696 } 697 698 func BenchmarkClearFat1040(b *testing.B) { 699 p := new([1040 / 4]uint32) 700 Escape(p) 701 b.ResetTimer() 702 for i := 0; i < b.N; i++ { 703 *p = [1040 / 4]uint32{} 704 } 705 } 706 707 func BenchmarkCopyFat7(b *testing.B) { 708 var x [7]byte 709 p := new([7]byte) 710 Escape(p) 711 b.ResetTimer() 712 for i := 0; i < b.N; i++ { 713 *p = x 714 } 715 } 716 717 func BenchmarkCopyFat8(b *testing.B) { 718 var x [8 / 4]uint32 719 p := new([8 / 4]uint32) 720 Escape(p) 721 b.ResetTimer() 722 for i := 0; i < b.N; i++ { 723 *p = x 724 } 725 } 726 727 func BenchmarkCopyFat11(b *testing.B) { 728 var x [11]byte 729 p := new([11]byte) 730 Escape(p) 731 b.ResetTimer() 732 for i := 0; i < b.N; i++ { 733 *p = x 734 } 735 } 736 737 func BenchmarkCopyFat12(b *testing.B) { 738 var x [12 / 4]uint32 739 p := new([12 / 4]uint32) 740 Escape(p) 741 b.ResetTimer() 742 for i := 0; i < b.N; i++ { 743 *p = x 744 } 745 } 746 747 func BenchmarkCopyFat13(b *testing.B) { 748 var x [13]byte 749 p := new([13]byte) 750 Escape(p) 751 b.ResetTimer() 752 for i := 0; i < b.N; i++ { 753 *p = x 754 } 755 } 756 757 func BenchmarkCopyFat14(b *testing.B) { 758 var x [14]byte 759 p := new([14]byte) 760 Escape(p) 761 b.ResetTimer() 762 for i := 0; i < b.N; i++ { 763 *p = x 764 } 765 } 766 767 func BenchmarkCopyFat15(b *testing.B) { 768 var x [15]byte 769 p := new([15]byte) 770 Escape(p) 771 b.ResetTimer() 772 for i := 0; i < b.N; i++ { 773 *p = x 774 } 775 } 776 777 func BenchmarkCopyFat16(b *testing.B) { 778 var x [16 / 4]uint32 779 p := new([16 / 4]uint32) 780 Escape(p) 781 b.ResetTimer() 782 for i := 0; i < b.N; i++ { 783 *p = x 784 } 785 } 786 787 func BenchmarkCopyFat24(b *testing.B) { 788 var x [24 / 4]uint32 789 p := new([24 / 4]uint32) 790 Escape(p) 791 b.ResetTimer() 792 for i := 0; i < b.N; i++ { 793 *p = x 794 } 795 } 796 797 func BenchmarkCopyFat32(b *testing.B) { 798 var x [32 / 4]uint32 799 p := new([32 / 4]uint32) 800 Escape(p) 801 b.ResetTimer() 802 for i := 0; i < b.N; i++ { 803 *p = x 804 } 805 } 806 807 func BenchmarkCopyFat64(b *testing.B) { 808 var x [64 / 4]uint32 809 p := new([64 / 4]uint32) 810 Escape(p) 811 b.ResetTimer() 812 for i := 0; i < b.N; i++ { 813 *p = x 814 } 815 } 816 817 func BenchmarkCopyFat72(b *testing.B) { 818 var x [72 / 4]uint32 819 p := new([72 / 4]uint32) 820 Escape(p) 821 b.ResetTimer() 822 for i := 0; i < b.N; i++ { 823 *p = x 824 } 825 } 826 827 func BenchmarkCopyFat128(b *testing.B) { 828 var x [128 / 4]uint32 829 p := new([128 / 4]uint32) 830 Escape(p) 831 b.ResetTimer() 832 for i := 0; i < b.N; i++ { 833 *p = x 834 } 835 } 836 837 func BenchmarkCopyFat256(b *testing.B) { 838 var x [256 / 4]uint32 839 p := new([256 / 4]uint32) 840 Escape(p) 841 b.ResetTimer() 842 for i := 0; i < b.N; i++ { 843 *p = x 844 } 845 } 846 847 func BenchmarkCopyFat512(b *testing.B) { 848 var x [512 / 4]uint32 849 p := new([512 / 4]uint32) 850 Escape(p) 851 b.ResetTimer() 852 for i := 0; i < b.N; i++ { 853 *p = x 854 } 855 } 856 857 func BenchmarkCopyFat520(b *testing.B) { 858 var x [520 / 4]uint32 859 p := new([520 / 4]uint32) 860 Escape(p) 861 b.ResetTimer() 862 for i := 0; i < b.N; i++ { 863 *p = x 864 } 865 } 866 867 func BenchmarkCopyFat1024(b *testing.B) { 868 var x [1024 / 4]uint32 869 p := new([1024 / 4]uint32) 870 Escape(p) 871 b.ResetTimer() 872 for i := 0; i < b.N; i++ { 873 *p = x 874 } 875 } 876 877 func BenchmarkCopyFat1032(b *testing.B) { 878 var x [1032 / 4]uint32 879 p := new([1032 / 4]uint32) 880 Escape(p) 881 b.ResetTimer() 882 for i := 0; i < b.N; i++ { 883 *p = x 884 } 885 } 886 887 func BenchmarkCopyFat1040(b *testing.B) { 888 var x [1040 / 4]uint32 889 p := new([1040 / 4]uint32) 890 Escape(p) 891 b.ResetTimer() 892 for i := 0; i < b.N; i++ { 893 *p = x 894 } 895 } 896 897 // BenchmarkIssue18740 ensures that memmove uses 4 and 8 byte load/store to move 4 and 8 bytes. 898 // It used to do 2 2-byte load/stores, which leads to a pipeline stall 899 // when we try to read the result with one 4-byte load. 900 func BenchmarkIssue18740(b *testing.B) { 901 benchmarks := []struct { 902 name string 903 nbyte int 904 f func([]byte) uint64 905 }{ 906 {"2byte", 2, func(buf []byte) uint64 { return uint64(binary.LittleEndian.Uint16(buf)) }}, 907 {"4byte", 4, func(buf []byte) uint64 { return uint64(binary.LittleEndian.Uint32(buf)) }}, 908 {"8byte", 8, func(buf []byte) uint64 { return binary.LittleEndian.Uint64(buf) }}, 909 } 910 911 var g [4096]byte 912 for _, bm := range benchmarks { 913 buf := make([]byte, bm.nbyte) 914 b.Run(bm.name, func(b *testing.B) { 915 for j := 0; j < b.N; j++ { 916 for i := 0; i < 4096; i += bm.nbyte { 917 copy(buf[:], g[i:]) 918 sink += bm.f(buf[:]) 919 } 920 } 921 }) 922 } 923 } 924 925 var memclrSink []int8 926 927 func BenchmarkMemclrKnownSize1(b *testing.B) { 928 var x [1]int8 929 930 b.SetBytes(1) 931 for i := 0; i < b.N; i++ { 932 for a := range x { 933 x[a] = 0 934 } 935 } 936 937 memclrSink = x[:] 938 } 939 func BenchmarkMemclrKnownSize2(b *testing.B) { 940 var x [2]int8 941 942 b.SetBytes(2) 943 for i := 0; i < b.N; i++ { 944 for a := range x { 945 x[a] = 0 946 } 947 } 948 949 memclrSink = x[:] 950 } 951 func BenchmarkMemclrKnownSize4(b *testing.B) { 952 var x [4]int8 953 954 b.SetBytes(4) 955 for i := 0; i < b.N; i++ { 956 for a := range x { 957 x[a] = 0 958 } 959 } 960 961 memclrSink = x[:] 962 } 963 func BenchmarkMemclrKnownSize8(b *testing.B) { 964 var x [8]int8 965 966 b.SetBytes(8) 967 for i := 0; i < b.N; i++ { 968 for a := range x { 969 x[a] = 0 970 } 971 } 972 973 memclrSink = x[:] 974 } 975 func BenchmarkMemclrKnownSize16(b *testing.B) { 976 var x [16]int8 977 978 b.SetBytes(16) 979 for i := 0; i < b.N; i++ { 980 for a := range x { 981 x[a] = 0 982 } 983 } 984 985 memclrSink = x[:] 986 } 987 func BenchmarkMemclrKnownSize32(b *testing.B) { 988 var x [32]int8 989 990 b.SetBytes(32) 991 for i := 0; i < b.N; i++ { 992 for a := range x { 993 x[a] = 0 994 } 995 } 996 997 memclrSink = x[:] 998 } 999 func BenchmarkMemclrKnownSize64(b *testing.B) { 1000 var x [64]int8 1001 1002 b.SetBytes(64) 1003 for i := 0; i < b.N; i++ { 1004 for a := range x { 1005 x[a] = 0 1006 } 1007 } 1008 1009 memclrSink = x[:] 1010 } 1011 func BenchmarkMemclrKnownSize112(b *testing.B) { 1012 var x [112]int8 1013 1014 b.SetBytes(112) 1015 for i := 0; i < b.N; i++ { 1016 for a := range x { 1017 x[a] = 0 1018 } 1019 } 1020 1021 memclrSink = x[:] 1022 } 1023 1024 func BenchmarkMemclrKnownSize128(b *testing.B) { 1025 var x [128]int8 1026 1027 b.SetBytes(128) 1028 for i := 0; i < b.N; i++ { 1029 for a := range x { 1030 x[a] = 0 1031 } 1032 } 1033 1034 memclrSink = x[:] 1035 } 1036 1037 func BenchmarkMemclrKnownSize192(b *testing.B) { 1038 var x [192]int8 1039 1040 b.SetBytes(192) 1041 for i := 0; i < b.N; i++ { 1042 for a := range x { 1043 x[a] = 0 1044 } 1045 } 1046 1047 memclrSink = x[:] 1048 } 1049 1050 func BenchmarkMemclrKnownSize248(b *testing.B) { 1051 var x [248]int8 1052 1053 b.SetBytes(248) 1054 for i := 0; i < b.N; i++ { 1055 for a := range x { 1056 x[a] = 0 1057 } 1058 } 1059 1060 memclrSink = x[:] 1061 } 1062 1063 func BenchmarkMemclrKnownSize256(b *testing.B) { 1064 var x [256]int8 1065 1066 b.SetBytes(256) 1067 for i := 0; i < b.N; i++ { 1068 for a := range x { 1069 x[a] = 0 1070 } 1071 } 1072 1073 memclrSink = x[:] 1074 } 1075 func BenchmarkMemclrKnownSize512(b *testing.B) { 1076 var x [512]int8 1077 1078 b.SetBytes(512) 1079 for i := 0; i < b.N; i++ { 1080 for a := range x { 1081 x[a] = 0 1082 } 1083 } 1084 1085 memclrSink = x[:] 1086 } 1087 func BenchmarkMemclrKnownSize1024(b *testing.B) { 1088 var x [1024]int8 1089 1090 b.SetBytes(1024) 1091 for i := 0; i < b.N; i++ { 1092 for a := range x { 1093 x[a] = 0 1094 } 1095 } 1096 1097 memclrSink = x[:] 1098 } 1099 func BenchmarkMemclrKnownSize4096(b *testing.B) { 1100 var x [4096]int8 1101 1102 b.SetBytes(4096) 1103 for i := 0; i < b.N; i++ { 1104 for a := range x { 1105 x[a] = 0 1106 } 1107 } 1108 1109 memclrSink = x[:] 1110 } 1111 func BenchmarkMemclrKnownSize512KiB(b *testing.B) { 1112 var x [524288]int8 1113 1114 b.SetBytes(524288) 1115 for i := 0; i < b.N; i++ { 1116 for a := range x { 1117 x[a] = 0 1118 } 1119 } 1120 1121 memclrSink = x[:] 1122 }